Skip to content

qspi_stream_ip驱动st77903的c程序(初稿)

minichao9901 edited this page Apr 20, 2024 · 2 revisions

说明

  • 刷8色图
  • 效率比较低,主要体现在xfer_cmd_pdata16函数的实现上

image

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xil_io.h"
#include "sleep.h"
//#include "ff.h"
#include "xil_cache.h"
#include "xtime_l.h"


#define  RED        0xF800
#define  ORANGE     0xFC00
#define  YELLOW     0xFFE0
#define  GREEN      0x07E0
#define  CYAN       0x07FF
#define  BLUE       0x001F
#define  PURPPLE    0xF81F
#define  BLACK      0x0000
#define  WHITE      0xFFFF
#define  GRAY       0xD69A

const u16 colors[] = {
	RED,
	GREEN,
	BLUE,
	ORANGE,
	YELLOW,
	CYAN,
	PURPPLE,
	BLACK,
	WHITE,
	GRAY
};

typedef struct{
	u8 txbuf[50];
	u8 rxbuf[50];
	u8 length;
}t_buf;

//#define BIST_MODE
t_buf WriteBuffer[]={
		{{0xf0, 0xc3}, {0x00},2},
		{{0xf0, 0x96}, {0x00},2},
		{{0xf0, 0xa5}, {0x00},2},
		{{0xe9, 0x20}, {0x00},2},
		{{0xe7,  0x80, 0x77, 0x1f, 0xcc}, {0x00}, 5},
		{{0xc1,  0x77, 0x07, 0xcf, 0x16}, {0x00},5},//Normal:VGHS/VGLS/VSP/VSN电压
		{{0xc2,  0x77, 0x07, 0xcf, 0x16}, {0x00},5},//Idle: VGHS/VGLS/VSP/VSN电压
		{{0xc3,  0x22, 0x02, 0x22, 0x04}, {0x00},5},//Normal: VGH/VGL/VSP/VSN Clk
		{{0xc4,  0x22, 0x02, 0x22, 0x04}, {0x00},5},//Idle: VGH/VGL/VSP/VSN Clk
		{{0xc5,  0xed},{0x00},2}, //VCOM
		{{0xe0, 0x87, 0x09, 0x0c, 0x06, 0x05, 0x03, 0x29, 0x32, 0x49, 0x0f, 0x1b, 0x17, 0x2a, 0x2f},{0x00},15},
		{{0xe1, 0x87, 0x09, 0x0c, 0x06, 0x05, 0x03, 0x29, 0x32, 0x49, 0x0f, 0x1b, 0x17, 0x2a, 0x2f},{0x00},15},
		{{0xe5, 0xbe, 0xf5, 0xb1, 0x22, 0x22, 0x25, 0x10, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22},{0x00},15},
		{{0xe6, 0xbe, 0xf5, 0xb1, 0x22, 0x22, 0x25, 0x10, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22},{0x00},15},
		{{0xec, 0x40, 0x03},{0x00},3},
		{{0x36,  0x0c},{0x00},2},
		{{0x3a,  0x07},{0x00},2},
		{{0xb2,  0x00},{0x00},2},//GIP pattern
		{{0xb3,  0x01},{0x00},2},//video mode dot-inversion
		{{0xb4,  0x01},{0x00},2},
		{{0xb5,  0x00, 0x08, 0x00, 0x08},{0x00},5}, //vfp
		{{0xb6,  0xc7, 0x31},{0x00},3},
		{{0xa5,  0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x2a, 0x8a, 0x02},{0x00},10},
		{{0xa6,  0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x2a, 0x8a, 0x02},{0x00},10},
		{{0xba,  0x0a, 0x5a, 0x23, 0x10, 0x25, 0x02, 0x00},{0x00},8},
		{{0xbb,  0x00, 0x30, 0x00, 0x2c, 0x82, 0x87, 0x18, 0x00},{0x00},9},
		{{0xbc,  0x00, 0x30, 0x00, 0x2c, 0x82, 0x87, 0x18, 0x00},{0x00},9},
		{{0xbd, 0xa1, 0xb2, 0x2b, 0x1a, 0x56, 0x43, 0x34, 0x65, 0xff, 0xff, 0x0f},{0x00},12},
		{{0x35,  0x00},{0x00},2},
		{{0x21},{0x00},1},
		{{0x11},{0x00},1},
		{{0xff},{0x00},0},
		{{0x29},{0x00},1},
		{{0xff},{0x00},0},
		#ifdef BIST_MODE
		{{0xb0,  0xa5},{0x00},2},
		{{0xcc,  0x40, 0x00, 0x3f, 0x00, 0x14, 0x14, 0x20, 0x20, 0x03},{0x00},10},
		#endif
};

/*************************************************
 * reg rw functions
 ************************************************/
#define DMA_BASE_ADRR  0x40000000
#define DDR_BASE_ADDR  0x10000000

void dma_xfer(u32 mem_addr, u32 length)
{
	Xil_Out32(DMA_BASE_ADRR,  0x00010003);
	Xil_Out32(DMA_BASE_ADRR+0x30,  0x00010003);
	Xil_Out32(DMA_BASE_ADRR+0x18,  DDR_BASE_ADDR+mem_addr);
	Xil_Out32(DMA_BASE_ADRR+0x28,  length);	 /*length is bytes*/
	usleep(10);
}

void set_cfg(u32 mem_addr, u8 cmd, u8 addr, u8 mode, u16 length)
{
	u32 tmp=cmd;
	tmp|=addr<<8;
	tmp|=mode<<16;
	tmp|=length<<20;
	Xil_Out32(DDR_BASE_ADDR+mem_addr,  tmp);
}

void set_npdata8(u32 mem_addr, u8 *pdata, u32 length){
	u32 addr=DDR_BASE_ADDR+mem_addr;
	while(length--){
		Xil_Out8(addr++, *pdata++);
	}
}

void set_npdata16_fast(u32 mem_addr, u16 *pdata, u32 length){
	/*每次传一个u32,数量减半*/
	u16 *ptmp=pdata;
	u32 addr=DDR_BASE_ADDR+mem_addr;
	while(length){
//		u16 tmp=((*ptmp&0xff)<<8)+(*ptmp>>8); /*msb&lsb swap*/
		u16 tmp1=*ptmp;
		u16 tmp2=*(ptmp+1);
		u32 tmp=(tmp2<<16)+tmp1;
		Xil_Out32(addr, tmp);
		addr+=4;
		ptmp+=2;
		length-=2;
	}
}


/*************************************************
 * basic xfer functions
 ************************************************/
void xfer_cmd_pdata8(u32 mem_addr, u8 cmd, u8* pdata, u32 length){
	if(length==0)
		set_cfg(mem_addr, 0xde, cmd, 0b0101, length);  /*byte_mode=0, cs_mode=1, data_mode=0b01*/
	else
		set_cfg(mem_addr, 0xde, cmd, 0b0110, length); /*byte_mode=0, cs_mode=1, data_mode=0b10*/

	set_npdata8(mem_addr+4, pdata,length);
	dma_xfer(mem_addr, 4+length);
}

void xfer_cmd_pdata16(u32 mem_addr, u8 cmd, u16* pdata, u32 length /*w16 counts*/){
	u32 remain=length;
	u32 mem_addr_keep=mem_addr;
	u32 max_burst_w16=30;
	u32 burst_cnt=0;

	while(remain>=max_burst_w16){
		if(remain>max_burst_w16)
			set_cfg(mem_addr, 0xde, cmd, 0b0011, 2*max_burst_w16);  /*byte_mode=0, cs_mode=0, data_mode=0b11*/
		else
			set_cfg(mem_addr, 0xde, cmd, 0b0111, 2*max_burst_w16);  /*byte_mode=0, cs_mode=1, data_mode=0b11*/

		set_npdata16_fast(mem_addr+4, pdata, max_burst_w16);
		pdata+=max_burst_w16;
		remain-=max_burst_w16;
		mem_addr+=4+2*max_burst_w16;
		burst_cnt++;
	}

	//last part
	if(remain>0){
		set_cfg(mem_addr, 0xde, cmd, 0b1111, 2*remain);  /*byte_mode=1, cs_mode=1, data_mode=0b11*/
		set_npdata16_fast(mem_addr+4, pdata, remain);
		burst_cnt++;
	}

	dma_xfer(mem_addr_keep, 64*burst_cnt);
}


void seqs_init() {

	for (int i = 0; i < sizeof(WriteBuffer) / sizeof(*WriteBuffer); i++) {
		if (WriteBuffer[i].length == 0) {
			usleep(WriteBuffer[i].txbuf[0] * 1000);
			continue;
		}

		u8 cmd=WriteBuffer[i].txbuf[0];
		u8 *pdata=WriteBuffer[i].txbuf+1;
		u16 length=WriteBuffer[i].length-1;

		xfer_cmd_pdata8(0x00, cmd, pdata, length);
		usleep(10); //this delay is need
		//xil_printf("Exec CMD=%x\r\n\r\n", cmd);
	}
}

/*************************************************
 * application functions
 ************************************************/

#define LCD_BPP             (24)

#define LCD_X_SIZE          (400U)                      /* available x pixel size */
#define LCD_Y_SIZE          (400U)		                /* available y pixle size */
#define LCD_PBYTE           ((LCD_BPP + 0) / 8)         /* bytes in pixel unit */
#define LCD_HBYTE           (LCD_X_SIZE * LCD_PBYTE)    /* bytes in horizontal line */

#define LCD_VSW             (1U)
#define LCD_HFP             (8U)
#define LCD_HBP             (8U)

#define LCD_TE_OFT          (25U)

//u8 line_data[LCD_HBYTE];
u8 *line_data=(u8 *)0x10010000;

void fill_data(u8 r, u8 g, u8 b)
{
	for(int i=0; i<LCD_HBYTE; i+=3){
		line_data[i]=r;
		line_data[i+1]=g;
		line_data[i+2]=b;
	}
}

void test()
{
	fill_data(0xff,0x00,0x00);
    while (1)
    {
//        /* TE signal */
//        rt_timer_start(&te_timer);

        /* vs(0x61) packet */
        for (int i = 0; i < LCD_VSW; i++)
        {
        	xfer_cmd_pdata8(0x00, 0x61,NULL,0);
            usleep(40);
        }

        /* hbp(0x60) packet */
        for (int i = 0; i < LCD_HBP; i++)
        {
        	xfer_cmd_pdata8(0x00, 0x60,NULL,0);
            usleep(40);
        }

        /* transmit display cache data to lcd line by line */
        for (int i = 0; i < LCD_Y_SIZE; i++)
        {
        	xfer_cmd_pdata16(0x00, 0x60, (u16 *)line_data, LCD_HBYTE/2);
        }

        /* hfp(0x60) packet */
        for (int i = 0; i < LCD_HFP; i++)
        {
        	xfer_cmd_pdata8(0x00, 0x60,NULL,0);
            usleep(40);
        }
    }

}

int main()
{
    init_platform();
    //cmda_init();
    //Xil_Disable_Cache_On_OCM();
    Xil_DCacheDisable();

    print("Hello World\n\r");

    //MY_QSPI_IP_Reg_SelfTest((void *)QSPI_BASE);

	seqs_init();
	test();

    //dram_eight_colors();
    //draw_bmp();
    //draw_movie();

    cleanup_platform();
    return 0;
}
Clone this wiki locally