-
Notifications
You must be signed in to change notification settings - Fork 0
qspi_stream_ip驱动st77903的c程序(初稿)
minichao9901 edited this page Apr 20, 2024
·
2 revisions
- 刷8色图
- 效率比较低,主要体现在xfer_cmd_pdata16函数的实现上
#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;
}