- void spi1_init(void)
- {
- gpio_init_typegpio_initstructure;
- spi_init_typespi_init_struct;
- crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);
- crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
- gpio_default_para_init(&gpio_initstructure);
- /* spi1 sck pin */
- gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
- gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
- gpio_initstructure.gpio_pull = GPIO_PULL_UP;
- gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
- gpio_initstructure.gpio_pins = GPIO_PINS_5;
- gpio_init(GPIOA, &gpio_initstructure);
- gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE5, GPIO_MUX_5);
- /* spi1 mosi pin */
- gpio_initstructure.gpio_pull = GPIO_PULL_UP;
- gpio_initstructure.gpio_pins = GPIO_PINS_7;
- gpio_init(GPIOA, &gpio_initstructure);
- gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_5);
- /* RST= PA2,DC=PA3 */
- gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
- gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
- gpio_initstructure.gpio_mode = GPIO_MODE_OUTPUT;
- gpio_initstructure.gpio_pins = GPIO_PINS_2 | GPIO_PINS_3;
- gpio_initstructure.gpio_pull = GPIO_PULL_UP;
- gpio_init(GPIOA, &gpio_initstructure);
- spi_default_para_init(&spi_init_struct);
- spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
- spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
- spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_4;
- spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
- spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
- spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
- spi_init_struct.clock_phase = SPI_CLOCK_PHASE_1EDGE;
- spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
- spi_init(SPI1, &spi_init_struct);
- spi_enable(SPI1, TRUE);
- }
- void spi_writebyte(uint8_t TxData)
- {
- while(spi_i2s_flag_get(SPI1, SPI_I2S_TDBE_FLAG) == RESET);
- spi_i2s_data_transmit(SPI1, TxData);
- }
3.3 LCD显示实现
上面已经实现了SPI 的驱动,以及8位发送,移植LCD的驱动代码,替换显示发送函数,以及IO定义。
写数据函数:
- <blockquote>void LCD_WR_DATA(u8 data)
写命令函数:
- void LCD_WR_REG(u8 data)
- {
- LCD_CS_CLR;
- LCD_RS_CLR;
- spi_writebyte(data);
- LCD_CS_SET;
- }
写16位数据函数:
- void Lcd_WriteData_16Bit(u16 Data)
- {
- LCD_CS_CLR;
- LCD_RS_SET;
- spi_writebyte(Data>>8);
- spi_writebyte(Data);
- LCD_CS_SET;
- }
LCD所用IO定义:
- #define LCD_CS_PIN GPIO_PINS_1
- #define LCD_RST_PIN GPIO_PINS_2
- #define LCD_DC_PIN GPIO_PINS_3
- #define gpio_x GPIOA
- //GPIOÖÃ루À¸ß£©
- #define LCD_CS_SET gpio_x->scr = LCD_CS_PIN //Ƭѡ¶Ë¿Ú
- #define LCD_RS_SET gpio_x->scr = LCD_DC_PIN //Êý¾Ý/ÃüÁî
- #define LCD_RST_SET gpio_x->scr = LCD_RST_PIN //¸´Î»
- //GPIO¸´Î»£¨ÀµÍ£©
- #define LCD_CS_CLR gpio_x->clr = LCD_CS_PIN //Ƭѡ¶Ë¿Ú
- #define LCD_RS_CLR gpio_x->clr = LCD_DC_PIN //Êý¾Ý/ÃüÁî
- #define LCD_RST_CLR gpio_x->clr = LCD_RST_PIN //¸´Î»
四、移植过程
添加NES源码:
添加源码路径:
nes_main主函数:
- void nes_main(void)
- {
- NesHeader *neshreader = (NesHeader *) rom_file;
- init6502mem( 0, /*exp_rom*/
- 0, /*sram ÓÉ¿¨ÀàÐ;ö¶¨, Ôݲ»Ö§³Ö*/
- (&rom_file[0x10]), /*prg_rombank, ´æ´¢Æ÷´óС ÓÉ¿¨ÀàÐ;ö¶¨*/
- neshreader->romnum
- ); //³õʼ»¯6502´æ´¢Æ÷¾µÏñ
- reset6502();
- PPU_Init((&rom_file[0x10] + (neshreader->romnum * 0x4000)),(neshreader->romfeature & 0x01)); /*PPU_³õʼ»¯*/
- //NES_JoyPadInit();
- NesFrameCycle();
- }
PPU显示每一行:
- void NES_RenderLine(int y_axes)
- {
- // static u8 flag=0;
- int i, render_spr_num, spr_size, dy_axes;
- PPU_Reg.R2 &= ~R2_LOST_SPR; //ÉèÖÃPPU״̬¼Ä´æÆ÷R2 SPR LOSTµÄ±ê־λ
- if(PPU_Reg.R1 & (R1_BG_VISIBLE | R1_SPR_VISIBLE)) //ÈôΪ¼Ù£¬¹Ø±ÕÏÔʾ£¬Ìî0ºÚ
- {
- /*Çå¿ÕÏÔʾ»º´æ£¬ÔÚ´ËÉèÖõױ³¾°É«£¨´ýÈ·¶¨£©*/
- for(i=0; i<(8 + 256 + 8) ; i++) //ÏÔÊ¾Çø 7 ~ 263 0~7 263~270 Ϊ·ÀÖ¹Òç³öÇø
- {
- Buffer_scanline[i] = NES_Color_Palette[PPU_Mem.image_palette[0]];
- }
- spr_size = PPU_Reg.R0 & R0_SPR_SIZE ? 0x0F : 0x07; //spr_size 8£º0~7£¬16: 0~15
- /* ɨÃè±³¾°sprite²¢×ª»»³ÉÏÔʾÊý¾ÝдÈëµ½»º´æ,ÿһÐÐ×î¶àÖ»ÄÜÏÔʾ8¸öSprite*/
- if(PPU_Reg.R1 & R1_SPR_VISIBLE) //Èô¿ªÆôspriteÏÔʾ
- {
- render_spr_num=0; //ÇåÁãÏÔʾ¼ÆÊýÆ÷
- for(i=63; i>=0; i--) //ÈôÖØµþsprites 0 ¾ßÓÐÏÔʾ×î¸ßÓÅÏȼ¶£¬ÆäÓàÓÅÏȼ¶Ë³Ðò´ÎÖ®£¬ËùÒÔ×îÏÈÏÔʾ×îµÍÓÅÏȼ¶
- {
- /*ÅжÏÏÔʾ²ã£¨·Ç£© ±³¾°*/
- if(!(sprite[i].attr & SPR_BG_PRIO))
- {
- continue; //(0=Sprite In front of BG, 1=Sprite Behind BG)
- }
- /*ÅжÏÏÔʾλÖÃ*/
- dy_axes = y_axes - (uint8)(sprite[i].y + 1); //ÅжÏspriteÊÇ·ñÔÚµ±Ç°ÐÐÏÔʾ·¶Î§ÄÚ,sprite y (FF,00,01,...EE)(0~239)
- if(dy_axes != (dy_axes & spr_size))
- {
- continue; //Èô²»ÔÚÔò·µ»Ø¼ÌÐøÑ»·²éÕÒÏÂÒ»¸ö
- }
- /*Èô´æÔÚspriteÔÚµ±Ç°ÏÔʾÐÐ,ÔòתÈëÏÂÃæÏÔʾ½×¶Î*/
- render_spr_num++; //ÒÑÏÔʾµÄspriteµÄÊýÄ¿+1
- if(render_spr_num > 8 ) //Ò»Ðг¬¹ý8¸öspreite£¬Ìø³öÑ»·
- {
- PPU_Reg.R2 |= R2_LOST_SPR; //ÉèÖÃPPU״̬¼Ä´æÆ÷R2µÄ±ê־λ
- break;
- }
- if(PPU_Reg.R0 & R0_SPR_SIZE) //ÈôÎªÕæ£¬spriteµÄ´óС8*16
- {
- NES_RenderSprite16(&sprite[i], dy_axes);
- }
- else //ÈôΪ¼Ù£¬spriteµÄ´óС8*8
- {
- NES_RenderSprite88(&sprite[i], dy_axes);
- }
- }
- }
- /* ɨÃè±³¾° background*/
- if(PPU_Reg.R1 & R1_BG_VISIBLE)
- {
- NES_RenderBGLine(y_axes); //ɨÃè²¢ÉèÖÃSprite #0Åöײ±êÖ¾
- }
- /* ɨÃèǰ¾°sprite²¢×ª»»³ÉÏÔʾÊý¾ÝдÈëµ½»º´æ,ÿһÐÐ×î¶àÖ»ÄÜÏÔʾ8¸öSprite*/
- if(PPU_Reg.R1 & R1_SPR_VISIBLE) //Èô¿ªÆôspriteÏÔʾ
- {
- render_spr_num=0; //ÇåÁãÏÔʾ¼ÆÊýÆ÷
- /* ÈôÖØµþsprites 0 ¾ßÓÐÏÔʾ×î¸ßÓÅÏȼ¶£¬ÆäÓàÓÅÏȼ¶Ë³Ðò´ÎÖ®£¬ËùÒÔ×îÏÈÏÔʾ×îµÍÓÅÏȼ¶
- * ±¸×¢£ºÈôǰ¾°sprites ÓÅÏȼ¶µÍÓÚ±³¾°ÓÅÏȼ¶£¬ÖصþµÄÑÕÉ«£¬Ç°¾°ÓÅÏȼ¶µÍÓÚ±³¾°ÓÅÏȼ¶µÄ»°£¬Ç°¾°½«²»»áÏÔʾ(ÔÝδ´¦Àí)*/
- for(i=63; i>=0; i--)
- {
- /*ÅжÏÏÔʾ²ã ǰ¾°*/
- if(sprite[i].attr & SPR_BG_PRIO)
- {
- continue; //(0=Sprite In front of BG, 1=Sprite Behind BG)
- }
- /*ÅжÏÏÔʾλÖÃ*/
- dy_axes = y_axes - ((int)sprite[i].y + 1); //ÅжÏspriteÊÇ·ñÔÚµ±Ç°ÐÐÏÔʾ·¶Î§ÄÚ,sprite y (FF,00,01,...EE)(0~239)
- if(dy_axes != (dy_axes & spr_size))
- {
- continue; //Èô²»ÔÚÔò·µ»Ø¼ÌÐøÑ»·²éÕÒÏÂÒ»¸ö
- }
- /*Èô´æÔÚspriteÔÚµ±Ç°ÏÔʾÐÐ,ÔòתÈëÏÂÃæÏÔʾ½×¶Î*/
- render_spr_num++; //ÒÑÏÔʾµÄspriteµÄÊýÄ¿+1
- if(render_spr_num > 8 ) //Ò»Ðг¬¹ý8¸öspreite£¬Ìø³öÑ»·
- {
- PPU_Reg.R2 |= R2_LOST_SPR; //ÉèÖÃPPU״̬¼Ä´æÆ÷R2µÄ±ê־λ
- break;
- }
- if(PPU_Reg.R0 & R0_SPR_SIZE) //ÈôÎªÕæ£¬spriteµÄ´óС8*16
- {
- NES_RenderSprite16(&sprite[i], dy_axes);
- }
- else //ÈôΪ¼Ù£¬spriteµÄ´óС8*8
- {
- NES_RenderSprite88(&sprite[i], dy_axes);
- }
- }
- }
- }
- else
- {
- for(i=0; i<(8 + 256 + 8); i++)
- {
- Buffer_scanline[i] = BLACK;//Çå¿ÕÏÔʾ»º´æ,ºÚÆÁ
- }
- }
- /*Íê³ÉɨÃ裬½«ÐÐÏÔʾ»º´æÐ´ÈëLCD*/
- NES_LCD_DisplayLine(y_axes, Buffer_scanline);//Æô¶¯LCDÏÔʾһÐУ¬²éѯ»òDMA´«ËÍ
- }
将行缓存写入LCD:
- void NES_LCD_DisplayLine(int y_axes, uint16 *Disaplyline_buffer)
- {
- u16 index;
- LCD_SetWindows(0,200,240,y_axes);
- LCD_WriteRAM_Prepare();
- for(index = 16; index < 256; index++)
- {
- Lcd_WriteData_16Bit( Buffer_scanline[index]);
- }
- }
显示效果如下: