Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] [stm32] F469 disco hardware rev b08 display driver nt35510 #1003

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/stm32f469_discovery/display/project.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<library>
<extends>modm:disco-f469ni</extends>
<extends>modm:disco-f469ni:b-08</extends>
<options>
<option name="modm:build:build.path">../../../build/stm32f469_discovery/display</option>
</options>
Expand Down
220 changes: 220 additions & 0 deletions src/modm/board/disco_f469ni/board_dsi_nt35510.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/*
* Copyright (c) 2016-2017, Niklas Hauser
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#include <modm/board.hpp>
#include <modm/platform/clock/rcc.hpp>

extern void
nt35510_init(uint8_t);

// ---------------------------------- DISPLAY ----------------------------------
void
board_initialize_display(uint8_t ColorCoding)
{
using namespace modm::platform;
if (Rcc::isEnabled<Peripheral::Ltdc>()) return;
// Enable clock to LTDC, DSI interface
Rcc::enable<Peripheral::Ltdc>();
Rcc::enable<Peripheral::Dsihost>();

{
// Expanded `HAL_DSI_Init()`:
// Enable regulator
DSI->WRPCR = DSI_WRPCR_REGEN;
// Wait until stable
for (int t = 1'024; not (DSI->WISR & DSI_WISR_RRS) and t; t--) {
modm::delay_ms(1);
}
// Set up PLL and enable it
DSI->WRPCR |= (0 << 16) | (2 << 11) | (125 << 2) | DSI_WRPCR_PLLEN;
// Wait until stable
for (int t = 1'024; not (DSI->WISR & DSI_WISR_PLLLS) and t; t--) {
modm::delay_ms(1);
}
// D-PHY clock and digital enable
DSI->PCTLR = DSI_PCTLR_CKE | DSI_PCTLR_DEN;
// Clock lane configuration
DSI->CLCR = DSI_CLCR_DPCC;
// Configure the number of active data lanes
DSI->PCONFR = 1;
// Set the TX escape clock division factor
DSI->CCR = 4;
// Calculate the bit period in high-speed mode in unit of 0.25 ns (UIX4)
// The equation is : UIX4 = IntegerPart( (1000/F_PHY_Mhz) * 4 )
// Where : F_PHY_Mhz = (NDIV * HSE_Mhz) / (IDF * ODF)
// Set the bit period in high-speed mode
DSI->WPCR[0] = 8;
// Disable all error interrupts and reset the Error Mask
DSI->IER[0] = 0;
DSI->IER[1] = 0;
}

constexpr uint32_t VSA = 2;
constexpr uint32_t VBP = 34;
constexpr uint32_t VFP = 34;

constexpr uint32_t HSA = 120;
constexpr uint32_t HBP = 150;
constexpr uint32_t HFP = 150;

constexpr uint32_t HACT = 800;
constexpr uint32_t VACT = 480;
const uint8_t pixel_size = (ColorCoding == 0) ? sizeof(uint32_t) : sizeof(uint16_t);
constexpr float ClockRatio = 62500.f / 27429;

{
// Expanded `HAL_DSI_ConfigVideoMode()`
// Select video mode by resetting CMDM and DSIM bits
DSI->MCR = 0;
DSI->WCFGR = 0;
// Configure the video mode transmission type
DSI->VMCR = 2;
// Configure the video packet size
DSI->VPCR = HACT;
// Set the chunks number to be transmitted through the DSI link
DSI->VCCR = 0;
// Set the size of the null packet
DSI->VNPCR = 0xFFF;
// Select the virtual channel for the LTDC interface traffic
DSI->LVCIDR = 0;
// Configure the polarity of control signals
DSI->LPCR = 0;
// Select the color coding for the host
DSI->LCOLCR = ColorCoding;
// Select the color coding for the wrapper
DSI->WCFGR = ColorCoding << 1;
// DSI_VSYNC_RISING
DSI->WCFGR = DSI_WCFGR_VSPOL;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks a bit odd. In Line 77, WCFGR is set to 0, then to ColorCoding <<1 and then to DSI_WCFGR_VSPOL.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second assignment should probably be DSI->WCFGR |= DSI_WCFGR_VSPOL;.

Thanks for catching this and notifying here!

// Set the Horizontal Synchronization Active (HSA) in lane byte clock cycles
DSI->VHSACR = HSA * ClockRatio;
// Set the Horizontal Back Porch (HBP) in lane byte clock cycles
DSI->VHBPCR = HBP * ClockRatio;
// Set the total line time (HLINE=HSA+HBP+HACT+HFP) in lane byte clock cycles
DSI->VLCR = (HACT + HSA + HBP + HFP) * ClockRatio;
// Set the Vertical Synchronization Active (VSA)
DSI->VVSACR = VSA;
// Set the Vertical Back Porch (VBP)
DSI->VVBPCR = VBP;
// Set the Vertical Front Porch (VFP)
DSI->VVFPCR = VFP;
// Set the Vertical Active period
DSI->VVACR = VACT;
// Low power largest packet size
// Low power VACT largest packet size
DSI->LPMCR = (64 << 16) | 64;
// Configure the command transmission mode
// Enable LP transition in HFP period
// Enable LP transition in HBP period
DSI->VMCR |= DSI_VMCR_LPCE | DSI_VMCR_LPHFPE | DSI_VMCR_LPHBPE | DSI_VMCR_LPVAE |
DSI_VMCR_LPVFPE | DSI_VMCR_LPVBPE | DSI_VMCR_LPVSAE;
}
{
// Enable the DSI host
DSI->CR = DSI_CR_EN;
// Enable the DSI wrapper
DSI->WCR = DSI_WCR_DSIEN;
}

/* done by SystemClock::enable()
{
// LCD clock configuration
// PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz
// PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 384 Mhz
// PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 384 MHz / 7 = 54.857 MHz
// LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_2 = 54.857 MHz / 2 = 27.429 MHz
RCC->PLLSAICFGR = (7 << 28) | (15 << 24) | (3 << 16) | (384 << 6);
// Select PLLSAI clock for 48MHz clocks
RCC->DCKCFGR = RCC_DCKCFGR_CK48MSEL;
// Enable PLLSAI
RCC->CR |= RCC_CR_PLLSAION;
for (int t = 1'024; not (RCC->CR & RCC_CR_PLLSAIRDY) and t; t--) {
modm::delay_ms(1);
}
}
*/

// What we messed up maybe -- just following what ST example does LOL
// {
// // HAL_LTDC_Init(&hltdc_eval);
// // Configures the HS, VS, DE and PC polarity
// // sets HS Polarity and VS Polarity to active high (LTDC_HSPOLARITY_AH, LTDC_VSPOLARITY_AH)
// LTDC->GCR = (1 << 31) | (1 << 30);
// // Sets Synchronization size
// LTDC->SSCR = (1 << 16) | (1);
// // Sets Accumulated Back porch
// LTDC->BPCR = (2 << 16) | (2);
// // Sets Accumulated Active Width
// LTDC->AWCR = (202 << 16) | (482);
// // Sets Total Width and Height
// LTDC->TWCR = (203 << 16) | (483);
// // Sets the background color value
// LTDC->BCCR = 0;
// // Enable LTDC by setting LTDCEN bit
// LTDC->GCR |= LTDC_GCR_LTDCEN;
// }


// what is done in otm8009a
// This actually makes LPWRE error goe
{
// HAL_LTDC_Init(&hltdc_eval);
// Configures the HS, VS, DE and PC polarity
LTDC->GCR = 0;
// Sets Synchronization size
LTDC->SSCR = ((HSA - 1) << 16) | (VSA - 1);
// Sets Accumulated Back porch
LTDC->BPCR = ((HSA + HBP - 1) << 16) | (VSA + VBP - 1);
// Sets Accumulated Active Width
LTDC->AWCR = ((HACT + HSA + HBP - 1) << 16) | (VACT + VSA + VBP - 1);
// Sets Total Width and Height
LTDC->TWCR = ((HACT + HSA + HBP + HFP - 1) << 16) | (VACT + VSA + VBP + VFP - 1);
// Sets the background color value
LTDC->BCCR = 0;
// Enable LTDC by setting LTDCEN bit
LTDC->GCR |= LTDC_GCR_LTDCEN;
}

{

// we might have messed this up
// HAL_LTDC_ConfigLayer()
// Configures the horizontal start and stop position
LTDC_Layer1->WHPCR =
(0 + ((LTDC->BPCR & LTDC_BPCR_AHBP) >> 16) + 1)
| ((200 + ((LTDC->BPCR & LTDC_BPCR_AHBP) >> 16)) << 16); // tmp
// Configures the vertical start and stop position
LTDC_Layer1->WVPCR = (0 + (LTDC->BPCR & LTDC_BPCR_AVBP) + 1)
| ((480 + (LTDC->BPCR & LTDC_BPCR_AVBP)) << 16);
// Specifies the pixel format
LTDC_Layer1->PFCR = ColorCoding;
// Configures the default color values
LTDC_Layer1->DCCR = 0x00000000;
// Specifies the constant alpha value
LTDC_Layer1->CACR = 0xff;
// Specifies the blending factors
LTDC_Layer1->BFCR = 0x00000005U | 0x00000400U;
// Configures the color frame buffer pitch in byte
LTDC_Layer1->CFBLR = ((800 * pixel_size) << 16) | ((800 * pixel_size) + 3);
// Configures the frame buffer line number
LTDC_Layer1->CFBLNR = 480;

/* Configured in display.cpp
// Configures the color frame buffer start address
LTDC_Layer1->CFBAR = buffer_address;
// Enable LTDC_Layer by setting LEN bit
LTDC_Layer1->CR = LTDC_LxCR_LEN;
// Sets the Reload type
LTDC->SRCR = LTDC_SRCR_IMR;
*/
}

nt35510_init(ColorCoding);
}
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,4 @@ board_initialize_display(uint8_t ColorCoding)
LTDC->SRCR = LTDC_SRCR_IMR;
*/
}
}
}
1 change: 1 addition & 0 deletions src/modm/board/disco_f469ni/board_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ void
modm_board_init(void)
{
// Reset LCD
Board::DisplayReset::setOutput(Gpio::OutputType::PushPull, Gpio::OutputSpeed::High);
Board::DisplayReset::setOutput(modm::Gpio::Low);
modm::delay_ms(20);
Board::DisplayReset::set();
Expand Down
Loading