Jump to content

stm32h7 fmc sd1963 800x480 working ok


Recommended Posts

MPU

int Mpu_Init(void)
{
    ///// SDIO
    MPU_Region_InitTypeDef MPU_InitStructSDIO;
    /// Disable the MPU
    HAL_MPU_Disable();

    /// Enable the MPU
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    MPU_Region_InitTypeDef MPU_InitStruct;
    HAL_MPU_Disable();
    MPU_InitStruct.Enable=MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress = 0x60000000;
    MPU_InitStruct.Size = MPU_REGION_SIZE_1MB; 
    MPU_InitStruct.AccessPermission=MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.TypeExtField=MPU_TEX_LEVEL0;
    MPU_InitStruct.IsCacheable=MPU_ACCESS_NOT_CACHEABLE;
    MPU_InitStruct.IsBufferable=MPU_ACCESS_BUFFERABLE;
    MPU_InitStruct.IsShareable=MPU_ACCESS_SHAREABLE;
    MPU_InitStruct.Number=MPU_REGION_NUMBER0;
    MPU_InitStruct.SubRegionDisable=0x00;
    MPU_InitStruct.DisableExec=MPU_INSTRUCTION_ACCESS_ENABLE;
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

/// board_H..
#ifndef _GDISP_LLD_BOARD_H
#define _GDISP_LLD_BOARD_H


#define LCD_PIN_PWM           GPIO_PIN_13
#define LCD_PORT_PWM          GPIOD

#define LCD_PIN_RESET         GPIO_PIN_11
#define LCD_PORT_RESET        GPIOD

#define SSD1963_DELAY(ms)        gfxSleepMilliseconds(ms)
#define SSD1963_RESET_PIN_SET    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11,GPIO_PIN_SET);
#define SSD1963_RESET_PIN_RESET  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11,GPIO_PIN_RESET);    

#define SSD1963_REG              (*((volatile unsigned short *) 0x60000000))
#define SSD1963_RAM              (*((volatile unsigned short *) 0x60040000))
#define SSD1963_WRITE_CMD(cmd)    SSD1963_REG=((unsigned short)cmd)
#define SSD1963_WRITE_DATA(data)  SSD1963_RAM=((unsigned short)data)
#define SSD1963_READ_DATA()       SSD1963_RAM
/*
static const LCD_Parameters	DisplayTimings[] = {
	// You need one of these array elements per display
	{
		800, 480,								// Panel width and height
		0, 0, 48,								// Horizontal Timings (back porch, front porch, pulse)
		CALC_PERIOD(800,0,0,48),				// Total Horizontal Period (calculated from above line)
		2, 2, 10,								// Vertical Timings (back porch, front porch, pulse)
		CALC_PERIOD(480,2,2,10),				// Total Vertical Period (calculated from above line)
		CALC_FPR(800,480,2,2,48,2,2,10,60ULL),	// FPR - the 60ULL is the frames per second. Note the ULL!
		gFalse,									// Flip horizontally
		gFalse									// Flip vertically
	},
};*/
#define PANEL_WIDTH               800
#define PANEL_HEIGHT              480
#define HORIZONTAL_BACK_PORCH     46
#define HORIZONTAL_FRONT_PORCH    210
#define HORIZONTAL_PULSE_WIDTH    1
#define HORIZONTAL_TOTAL          1056
#define VERTICAL_BACK_PORCH       23
#define VERTICAL_FRONT_PORCH      22
#define VERTICAL_PULSE_WIDTH      1
#define VERTICAL_TOTAL            525

static const LCD_Parameters DisplayTimings[] = {
        // You need one of these array elements per display
        {
        PANEL_WIDTH, PANEL_HEIGHT,
        HORIZONTAL_BACK_PORCH,  HORIZONTAL_FRONT_PORCH, HORIZONTAL_PULSE_WIDTH,
        CALC_PERIOD(PANEL_WIDTH,HORIZONTAL_BACK_PORCH,  HORIZONTAL_FRONT_PORCH,HORIZONTAL_BACK_PORCH), ///  HORIZONTAL_TOTAL
        VERTICAL_BACK_PORCH,      VERTICAL_FRONT_PORCH, VERTICAL_PULSE_WIDTH,
        CALC_PERIOD(PANEL_HEIGHT, VERTICAL_BACK_PORCH,      VERTICAL_FRONT_PORCH,HORIZONTAL_BACK_PORCH),
        //CALC_FPR(PANEL_WIDTH,480,2,2,48,2,2,10,60ULL)
        HORIZONTAL_TOTAL * VERTICAL_TOTAL * 60ULL * 1048576 / 100000000,
		gFalse,									// Flip horizontally
		gTrue									// Flip vertically
        },
};

static GFXINLINE void init_board(GDisplay *g)
{
	(void) g;
    GPIO_InitTypeDef          gpio = {0};
    SRAM_HandleTypeDef        hsram1 = {0};
    FMC_NORSRAM_TimingTypeDef Timing = {0};
    FMC_NORSRAM_TimingTypeDef ExtTiming = {0};
    
    
    /// Pwm
    gpio.Pin   = LCD_PIN_PWM;
    gpio.Mode  = GPIO_MODE_OUTPUT_PP;
    gpio.Pull  = GPIO_NOPULL;
    gpio.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(LCD_PORT_PWM, &gpio);
    
    /// Reset
    gpio.Pin   = LCD_PIN_RESET;
    gpio.Mode  = GPIO_MODE_OUTPUT_PP;
    gpio.Pull  = GPIO_NOPULL;
    gpio.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(LCD_PORT_RESET, &gpio);
    

    __HAL_RCC_FMC_CLK_ENABLE();
    /// FMC GPIO Configuration
    /// PE7   ------> FMC_D4
    /// PE8   ------> FMC_D5
    /// PE9   ------> FMC_D6
    /// PE10   ------> FMC_D7
    /// PE11   ------> FMC_D8
    /// PE12   ------> FMC_D9
    /// PE13   ------> FMC_D10
    /// PE14   ------> FMC_D11
    /// PE15   ------> FMC_D12
    /// PD8   ------> FMC_D13
    /// PD9   ------> FMC_D14
    /// PD10   ------> FMC_D15
    /// PD12   ------> FMC_A17
    /// PD14   ------> FMC_D0
    /// PD15   ------> FMC_D1
    /// PD0   ------> FMC_D2
    /// PD1   ------> FMC_D3
    /// PD4   ------> FMC_NOE
    /// PD5   ------> FMC_NWE
    /// PD7   ------> FMC_NE1
    gpio.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 
              |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 
              |GPIO_PIN_15;

    gpio.Mode      = GPIO_MODE_AF_PP;
    gpio.Pull      = GPIO_NOPULL;
    gpio.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
    gpio.Alternate = GPIO_AF12_FMC;
    HAL_GPIO_Init(GPIOE, &gpio);

    gpio.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_12 
              |GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1 
              |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7;
                          
    gpio.Mode = GPIO_MODE_AF_PP;
    gpio.Pull = GPIO_NOPULL;
    gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    gpio.Alternate = GPIO_AF12_FMC;
    HAL_GPIO_Init(GPIOD, &gpio);
    
    /// USER CODE BEGIN FMC_MspInit 1
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11,GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_SET);

    /// Perform the SRAM1 memory initialization sequence
    hsram1.Instance = FMC_NORSRAM_DEVICE;
    hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
    /// hsram1.Init
    hsram1.Init.NSBank = FMC_NORSRAM_BANK1;
    hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
    hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
    hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
    hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
    hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
    hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
    hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
    hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
    hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_ENABLE;
    hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
    hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
    hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
    hsram1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
    hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
    /// Timing
    Timing.AddressSetupTime = 3;
    Timing.AddressHoldTime = 15;
    Timing.DataSetupTime = 14;
    Timing.BusTurnAroundDuration = 0;
    Timing.CLKDivision = 16;
    Timing.DataLatency = 17;
    Timing.AccessMode = FMC_ACCESS_MODE_A;
    /// ExtTiming
    ExtTiming.AddressSetupTime = 1;
    ExtTiming.AddressHoldTime = 15;
    ExtTiming.DataSetupTime = 2;
    ExtTiming.BusTurnAroundDuration = 0;
    ExtTiming.CLKDivision = 16;
    ExtTiming.DataLatency = 17;
    ExtTiming.AccessMode = FMC_ACCESS_MODE_A;
    
    if (HAL_SRAM_Init(&hsram1, &Timing, &ExtTiming) != HAL_OK)
    {
        Error_Handler( );
    }    
    
}

static GFXINLINE void post_init_board(GDisplay *g)
{
	(void) g;
}

static GFXINLINE void setpin_reset(GDisplay *g, gBool state) {
	(void) g;
	(void) state;
    if(state==gFalse)
    {
        printf("SSD1963_RESET_PIN_SET\n\r");
        SSD1963_RESET_PIN_SET;
    }
    else
    {
        printf("SSD1963_RESET_PIN_RESET\n\r");
        SSD1963_RESET_PIN_RESET;
    }
}

static GFXINLINE void acquire_bus(GDisplay *g) {
	(void) g;
}

static GFXINLINE void release_bus(GDisplay *g) {
	(void) g;
}

static GFXINLINE void write_index(GDisplay *g, gU16 index) {
	(void) g;
	(void) index;
    SSD1963_WRITE_CMD(index); 
}

static GFXINLINE void write_data(GDisplay *g, gU16 data) {
	(void) g;
	(void) data;
    SSD1963_WRITE_DATA(data);
}

#endif /* _GDISP_LLD_BOARD_H */


/// gdisp_lld_ssd1963
LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g)
{
    unsigned short color_bus;
    acquire_bus(g);
    set_viewport(g);
    write_index(g, SSD1963_READ_MEMORY_START);
    color_bus = SSD1963_READ_DATA();
    release_bus(g);
    return  (color_t)color_bus ;
}

LLDSPEC gBool gdisp_lld_init(GDisplay *g)
{
	LCD_Parameters *	lcdp;

    ///	Some displays (e.g. Displaytech) have an on-board setup process which just requires that we don't touch anything for a time after power up.
    /// For this type of display define GDISP_SSD1963_NO_INIT as TRUE, and implement an appropriate delay in the board file.
    ///	With such displays we can skip most of the initialisation. We also skip pulsing the reset pin, since it
    ///	will introduce an extra second or so of display to the startup time.
   
	// The private area for this controller is the LCD timings
	lcdp = (void *)&DisplayTimings[g->controllerdisplay];
	g->priv = lcdp;

	// Initialise the board interface
	init_board(g);
 

///	Some displays (e.g. Displaytech) have an on-board setup process which just requires that we don't touch anything for a time after power up.
///	For this type of display define GDISP_SSD1963_NO_INIT as GFXON, and implement an appropriate delay in the board file.
///	With such displays we can skip most of the initialisation. We also skip pulsing the reset pin, since it
///	will introduce an extra second or so of display to the startup time.
 
	// The private area for this controller is the LCD timings
	lcdp = (void *)&DisplayTimings[g->controllerdisplay];
	g->priv = lcdp;

	// Initialise the board interface
	//init_board(g);

	#if !GDISP_SSD1963_NO_INIT
		// Hardware reset
		setpin_reset(g, gTrue);
		gfxSleepMilliseconds(5);
		setpin_reset(g, gFalse);
		gfxSleepMilliseconds(5);
	#endif

	// Get the bus for the following initialisation commands
	acquire_bus(g);

	#if !GDISP_SSD1963_NO_INIT
		write_index(g, SSD1963_SOFT_RESET);             // Software reset - clears almost everything (apart from PLL)
		write_index(g, SSD1963_SOFT_RESET);             // Software reset - clears almost everything (apart from PLL)
		write_index(g, SSD1963_SOFT_RESET);             // Software reset - clears almost everything (apart from PLL)
		gfxSleepMilliseconds(5);
		/// Driver PLL config
		write_index(g, SSD1963_SET_PLL_MN);
		write_data(g, 35);								// PLLclk = REFclk (10Mhz) * 36 (360Mhz)
		write_data(g, 2);								// SYSclk = PLLclk / 3  (120MHz)
		write_data(g, 54);								// Apply calculation bit, else it is ignored        
        
		write_reg(g, SSD1963_SET_PLL, 0x01);			// Enable PLL
		gfxSleepMilliseconds(5);                
        /*write_reg(g, SSD1963_SET_PLL, 0x03);			// Use PLL
        */
        write_index(g, SSD1963_SET_PLL);        
        gfxSleepMilliseconds(1);  /// !!!!
        write_data(g, 0x03);
        gfxSleepMilliseconds(1); /// !!!!
        
        //SSD1963_WRITE_CMD(0x00E6);              /// PLL setting for PCLK, depends on resolution
        //SSD1963_WRITE_DATA(0x0003);
        //SSD1963_WRITE_DATA(0x00FF);
        //SSD1963_WRITE_DATA(0x00FF);

		/// LCD panel parameters
		write_index(g, SSD1963_SET_LCD_MODE);
		write_data(g, lcdp->mode & 0xFF);
		write_data(g, (lcdp->mode >> 8) & 0xFF);
		///	write_data(g, 0x18);					//Enabled dithering
		///	write_data(g, 0x00);
		write_data16(g, lcdp->width-1);
		write_data16(g, lcdp->height-1);
		write_data(g, 0x00);							// RGB - line sequences for serial TFT
	#endif

	/// Display flipping
	if (lcdp->flipHorz)
    {
		write_reg(g, SSD1963_SET_ADDRESS_MODE, SSD1963_ADDR_MODE_FLIP_HORZ);
	} else if (lcdp->flipVert)
    {
		write_reg(g, SSD1963_SET_ADDRESS_MODE, SSD1963_ADDR_MODE_FLIP_VERT);
	} else if (lcdp->flipHorz && lcdp->flipVert)
    {
		write_reg(g, SSD1963_SET_ADDRESS_MODE, SSD1963_ADDR_MODE_FLIP_VERT | SSD1963_ADDR_MODE_FLIP_HORZ);
	}
    else
    {
		write_reg(g, SSD1963_SET_ADDRESS_MODE, 0x00);
	}


	write_reg(g, SSD1963_SET_PIXEL_DATA_INTERFACE, SSD1963_PDI_16BIT565);
	write_reg(g, SSD1963_SET_PIXEL_FORMAT, 0x50);
    

	#if !GDISP_SSD1963_NO_INIT
		/// LCD Clock specs
        
		write_index(g, SSD1963_SET_LSHIFT_FREQ);
		write_data(g, (lcdp->fpr >> 16) & 0xFF);
		write_data(g, (lcdp->fpr >> 8) & 0xFF);
		write_data(g, lcdp->fpr & 0xFF);

		write_index(g, SSD1963_SET_HORI_PERIOD);
		write_data16(g, lcdp->hperiod);
		write_data16(g, lcdp->hpulse + lcdp->hbporch);        
		write_data(g, lcdp->hpulse - 1);
		write_data(g, 0x00);
		write_data(g, 0x00);
		write_data(g, 0x00);


		write_index(g, SSD1963_SET_VERT_PERIOD);
		write_data16(g, lcdp->vperiod);
		write_data16(g, lcdp->vpulse + lcdp->vbporch);
		write_data(g, lcdp->vpulse - 1);
		write_data(g, 0x00);
		write_data(g, 0x00);

		#if 0
			/// Enable DBC to control Backlight
			write_index(g, SSD1963_SET_DBC_CONF);
			write_data(g, 0x2F);
		#endif
	#endif

/*
	#if 0
		/// Tear effect indicator ON. This is used to tell the host MCU when the driver is not refreshing the panel (during front/back porch) 
		write_reg(g, SSD1963_SET_TEAR_ON, 0x00);
	#endif
*/

	/// Turn on
	write_index(g, SSD1963_SET_DISPLAY_ON);
	
	/// Turn on the back-light
	set_backlight(g, GDISP_INITIAL_BACKLIGHT);

	// Finish Init
	post_init_board(g);

	// Release the bus
	release_bus(g);

	/// Initialise the GDISP structure
    
	g->g.Width = lcdp->width;
	g->g.Height = lcdp->height;
	g->g.Orientation = gOrientation0;
	g->g.Powermode = gPowerOn;
	g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
	g->g.Contrast = GDISP_INITIAL_CONTRAST;
    
    HAL_GPIO_WritePin(LCD_PORT_PWM, LCD_PIN_PWM, GPIO_PIN_SET);
	return gTrue;
}

 

Edited by nicks1980
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...