From c5162d97ad6059cfea292beaf3b9a7b67ca8f982 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Wed, 3 Aug 2016 12:55:46 +0200 Subject: ucoo/hal/frame_buffer: add LTDC, DSI & DMA2D --- ucoo/arch/reg.stm32f4.hh | 5 + ucoo/hal/frame_buffer/Module | 6 +- ucoo/hal/frame_buffer/dma2d.stm32f4.cc | 187 ++++++++++++++++++++++++++++ ucoo/hal/frame_buffer/dma2d.stm32f4.hh | 49 ++++++++ ucoo/hal/frame_buffer/dsi.stm32f4.cc | 218 +++++++++++++++++++++++++++++++++ ucoo/hal/frame_buffer/dsi.stm32f4.hh | 56 +++++++++ ucoo/hal/frame_buffer/ltdc.stm32f4.cc | 86 +++++++++++++ ucoo/hal/frame_buffer/ltdc.stm32f4.hh | 53 ++++++++ 8 files changed, 659 insertions(+), 1 deletion(-) create mode 100644 ucoo/hal/frame_buffer/dma2d.stm32f4.cc create mode 100644 ucoo/hal/frame_buffer/dma2d.stm32f4.hh create mode 100644 ucoo/hal/frame_buffer/dsi.stm32f4.cc create mode 100644 ucoo/hal/frame_buffer/dsi.stm32f4.hh create mode 100644 ucoo/hal/frame_buffer/ltdc.stm32f4.cc create mode 100644 ucoo/hal/frame_buffer/ltdc.stm32f4.hh (limited to 'ucoo') diff --git a/ucoo/arch/reg.stm32f4.hh b/ucoo/arch/reg.stm32f4.hh index 1f5f2cf..6cedaba 100644 --- a/ucoo/arch/reg.stm32f4.hh +++ b/ucoo/arch/reg.stm32f4.hh @@ -128,6 +128,11 @@ #define DESIG_FLASH_SIZE_BASE 0x1fff7a22 #define DESIG_UNIQUE_ID_BASE 0x1fff7a10 +#define DMA2D_CR_MODE_MemoryToMemory 0 +#define DMA2D_CR_MODE_MemoryToMemoryFPC DMA2D_CR_MODE_0 +#define DMA2D_CR_MODE_MemoryToMemoryBlend DMA2D_CR_MODE_1 +#define DMA2D_CR_MODE_RegisterToMemory (DMA2D_CR_MODE_1 | DMA2D_CR_MODE_0) + #ifdef DSI_BASE # define DSI_VMCR_VMT_NonBurstSyncPulses 0 # define DSI_VMCR_VMT_NonBurstSyncEvents 1 diff --git a/ucoo/hal/frame_buffer/Module b/ucoo/hal/frame_buffer/Module index 699de5b..b4c2e40 100644 --- a/ucoo/hal/frame_buffer/Module +++ b/ucoo/hal/frame_buffer/Module @@ -1,4 +1,8 @@ -ucoo_hal_frame_buffer_SOURCES := sdl_frame_buffer.host.cc +ucoo_hal_frame_buffer_SOURCES := \ + dma2d.stm32f4.cc \ + dsi.stm32f4.cc \ + ltdc.stm32f4.cc \ + sdl_frame_buffer.host.cc SDL_CFLAGS = $(shell sdl2-config --cflags) SDL_LIBS = $(shell sdl2-config --libs) diff --git a/ucoo/hal/frame_buffer/dma2d.stm32f4.cc b/ucoo/hal/frame_buffer/dma2d.stm32f4.cc new file mode 100644 index 0000000..3ec0dad --- /dev/null +++ b/ucoo/hal/frame_buffer/dma2d.stm32f4.cc @@ -0,0 +1,187 @@ +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2016 Nicolas Schodet +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// }}} +#include "ucoo/hal/frame_buffer/dma2d.stm32f4.hh" +#include "ucoo/arch/reg.hh" + +namespace ucoo { + +void +dma2d_wait () +{ + while (reg::DMA2D->CR & DMA2D_CR_START) + ; +} + +void +dma2d_fill (Surface &dst, const Surface::Rect &rect, uint32_t color) +{ + // Handle clipping. + int x = rect.x, y = rect.y, w = rect.w, h = rect.h; + if (x < 0) + { + w += x; + x = 0; + } + if (y < 0) + { + h += y; + y = 0; + } + if (x + w > dst.w) + w = dst.w - x; + if (y + h > dst.h) + h = dst.h - y; + if (w < 0 || h < 0) + return; + // Wait for DMA2D to be idle. + dma2d_wait (); + // Fill. + switch (dst.format) + { + case Surface::Format::ARGB8888: + case Surface::Format::RGB888: + reg::DMA2D->OCOLR = color; + break; + case Surface::Format::RGB565: + { + uint32_t r = (color >> 19) & 0x1f; + uint32_t g = (color >> 10) & 0x3f; + uint32_t b = (color >> 3) & 0x1f; + reg::DMA2D->OCOLR = r << 11 | g << 5 | b; + } + break; + case Surface::Format::ARGB4444: + { + uint32_t r = (color >> 20) & 0xf; + uint32_t g = (color >> 12) & 0xf; + uint32_t b = (color >> 4) & 0xf; + reg::DMA2D->OCOLR = r << 8 | g << 4 | b; + } + break; + case Surface::Format::A8: + case Surface::Format::A4: + assert_unreachable (); + } + int bpp = dst.bpp (); + reg::DMA2D->OPFCCR = static_cast (dst.format) & 0xff; + reg::DMA2D->OMAR = reinterpret_cast (dst.pixels) + + (y * dst.stride + x) * bpp / 8; + reg::DMA2D->OOR = dst.stride - w; + reg::DMA2D->NLR = w << 16 | h; + reg::DMA2D->CR = DMA2D_CR_MODE_RegisterToMemory | DMA2D_CR_START; +} + +void +dma2d_blit (const Surface &dst, const Surface &src, int x, int y) +{ + int sx = 0, sy = 0, sw = src.w, sh = src.h; + // Handle clipping. + if (x < 0) + { + sw += x; + sx = -x; + x = 0; + } + if (y < 0) + { + sh += y; + sy = -y; + y = 0; + } + if (x + sw > dst.w) + sw = dst.w - x; + if (y + sh > dst.h) + sh = dst.h - y; + if (sw < 0 || sh < 0) + return; + // Wait for DMA2D to be idle. + dma2d_wait (); + // Blit. + int srcbpp = src.bpp (); + int dstbpp = dst.bpp (); + reg::DMA2D->FGMAR = reinterpret_cast (src.pixels) + + (sy * src.stride + sx) * srcbpp / 8; + reg::DMA2D->FGOR = src.stride - sw; + reg::DMA2D->FGPFCCR = static_cast (src.format) & 0xff; + reg::DMA2D->OPFCCR = static_cast (dst.format) & 0xff; + reg::DMA2D->OMAR = reinterpret_cast (dst.pixels) + + (y * dst.stride + x) * dstbpp / 8; + reg::DMA2D->OOR = dst.stride - sw; + reg::DMA2D->NLR = sw << 16 | sh; + if (src.format == dst.format) + reg::DMA2D->CR = DMA2D_CR_MODE_MemoryToMemory | DMA2D_CR_START; + else + reg::DMA2D->CR = DMA2D_CR_MODE_MemoryToMemoryFPC | DMA2D_CR_START; +} + +void +dma2d_blend (const Surface &dst, const Surface &src, int x, int y, + uint32_t const_color) +{ + int sx = 0, sy = 0, sw = src.w, sh = src.h; + // Handle clipping. + if (x < 0) + { + sw += x; + sx = -x; + x = 0; + } + if (y < 0) + { + sh += y; + sy = -y; + y = 0; + } + if (x + sw > dst.w) + sw = dst.w - x; + if (y + sh > dst.h) + sh = dst.h - y; + if (sw < 0 || sh < 0) + return; + // Wait for DMA2D to be idle. + dma2d_wait (); + // Blend. + int srcbpp = src.bpp (); + int dstbpp = dst.bpp (); + reg::DMA2D->FGMAR = reinterpret_cast (src.pixels) + + (sy * src.stride + sx) * srcbpp / 8; + reg::DMA2D->FGOR = src.stride - sw; + uint32_t bgmar = reinterpret_cast (dst.pixels) + + (y * dst.stride + x) * dstbpp / 8; + reg::DMA2D->BGMAR = bgmar; + uint32_t bgor = dst.stride - sw; + reg::DMA2D->BGOR = bgor; + reg::DMA2D->FGPFCCR = (const_color & 0xff000000) + | DMA2D_FGPFCCR_AM_1 + | (static_cast (src.format) & 0xff); + reg::DMA2D->FGCOLR = const_color & 0xffffff; + reg::DMA2D->BGPFCCR = static_cast (dst.format) & 0xff; + reg::DMA2D->OPFCCR = static_cast (dst.format) & 0xff; + reg::DMA2D->OMAR = bgmar; + reg::DMA2D->OOR = bgor; + reg::DMA2D->NLR = sw << 16 | sh; + reg::DMA2D->CR = DMA2D_CR_MODE_MemoryToMemoryBlend | DMA2D_CR_START; +} + +} // namespace ucoo diff --git a/ucoo/hal/frame_buffer/dma2d.stm32f4.hh b/ucoo/hal/frame_buffer/dma2d.stm32f4.hh new file mode 100644 index 0000000..f70ead2 --- /dev/null +++ b/ucoo/hal/frame_buffer/dma2d.stm32f4.hh @@ -0,0 +1,49 @@ +#ifndef ucoo_hal_frame_buffer_dma2d_stm32_hh +#define ucoo_hal_frame_buffer_dma2d_stm32_hh +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2016 Nicolas Schodet +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// }}} +#include "ucoo/intf/frame_buffer.hh" + +namespace ucoo { + +/// Wait until all operations are done. +void +dma2d_wait (); + +/// Fill given rect in surface, with clipping. +void +dma2d_fill (Surface &dst, const Surface::Rect &rect, uint32_t color); + +/// Blit surface in another surface, with clipping. +void +dma2d_blit (const Surface &dst, const Surface &src, int x, int y); + +/// Blend surface in another surface, with clipping. +void +dma2d_blend (const Surface &dst, const Surface &src, int x, int y, + uint32_t const_color = 0xff000000); + +} // namespace ucoo + +#endif // ucoo_hal_frame_buffer_dma2d_stm32_hh diff --git a/ucoo/hal/frame_buffer/dsi.stm32f4.cc b/ucoo/hal/frame_buffer/dsi.stm32f4.cc new file mode 100644 index 0000000..31a71f4 --- /dev/null +++ b/ucoo/hal/frame_buffer/dsi.stm32f4.cc @@ -0,0 +1,218 @@ +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2016 Nicolas Schodet +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// }}} +#include "ucoo/hal/frame_buffer/dsi.stm32f4.hh" + +#include "ucoo/arch/reg.hh" +#include "ucoo/arch/rcc.stm32.hh" + +namespace ucoo { + +enum DsiDataType +{ + SYNC_EVENT_VSYNC_START = 0x01, + SYNC_EVENT_VSYNC_END = 0x11, + SYNC_EVENT_HSYNC_START = 0x21, + SYNC_EVENT_HSYNC_END = 0x31, + END_OF_TRANSMISSION = 0x08, + COLOR_MODE_OFF = 0x02, + COLOR_MODE_ON = 0x12, + NULL_PACKET = 0x09, + BLANKING_PACKET = 0x19, + GENERIC_SHORT_WRITE_PARAM_0 = 0x03, + GENERIC_SHORT_WRITE_PARAM_1 = 0x13, + GENERIC_SHORT_WRITE_PARAM_2 = 0x23, + GENERIC_READ_PARAM_0 = 0x04, + GENERIC_READ_PARAM_1 = 0x14, + GENERIC_READ_PARAM_2 = 0x24, + DCS_SHORT_WRITE_PARAM_0 = 0x05, + DCS_SHORT_WRITE_PARAM_1 = 0x15, + DCS_READ = 0x06, + SET_MAX_RETURN_SIZE = 0x37, + GENERIC_LONG_WRITE = 0x29, + DCS_LONG_WRITE = 0x39, + PACKED_PIXEL_RGB565 = 0x0e, + PACKED_PIXEL_RGB666 = 0x1e, + PACKED_PIXEL_RGB666_LOOSE = 0x2e, + PACKED_PIXEL_RGB888 = 0x3e, +}; + +Dsi::Dsi (int width, int heigth, int lanes) + : Ltdc (width, heigth, 2, 1, 1, 2, 1, 1), lanes_ (lanes) +{ +} + +void +Dsi::enable (const Function &config) +{ + // TODO: make this more configurable. + // Enable clocks. + rcc_peripheral_clock_enable (Rcc::DSI); + // Enable DSI regulator. + reg::DSI->WRPCR = DSI_WRPCR_REGEN; + while (!(reg::DSI->WISR & DSI_WISR_RRS)) + ; + // Enable PLL, 500 MHz output frequency (HSE @ 8 MHz). + const int phy_hz = 500000000; + reg::DSI->WRPCR = DSI_WRPCR_REGEN + | (125 << DSI_WRPCR_PLL_NDIV_Pos) + | (2 << DSI_WRPCR_PLL_IDF_Pos) + | DSI_WRPCR_PLL_ODF_Div1; + reg::DSI->WRPCR |= DSI_WRPCR_PLLEN; + while (!(reg::DSI->WISR & DSI_WISR_PLLLS)) + ; + //// D-PHY parameters. + // Setup Unit interval. + reg::DSI->WPCR[0] = 4000000000u / phy_hz; + // Number of lanes. + reg::DSI->PCONFR = lanes_ - 1; + // Clock control. + reg::DSI->CLCR = DSI_CLCR_DPCC; + // TODO: Time for LP/HS and HS/LP transition in CLTCR/DLTCR. + // TODO: Stop wait time in PCONFR. + //// Timings. + // TX escape clock division factor. + reg::DSI->CCR = 4; // 500 MHz / 8 (bit) / 4 < 20 MHz + // TX timeouts. + reg::DSI->CCR |= 4 << 8; + reg::DSI->TCCR[0] = 0x01000000; + reg::DSI->TCCR[1] = 0x00000100; + reg::DSI->TCCR[2] = 0x00000100; + reg::DSI->TCCR[3] = 0x00000100; + reg::DSI->TCCR[4] = 0x00000100; + reg::DSI->TCCR[5] = 0x00000100; + //// Flow control & DBI interface. + reg::DSI->CMCR = DSI_CMCR_GSW0TX | DSI_CMCR_GSW1TX | DSI_CMCR_GSW2TX + | DSI_CMCR_GSR0TX | DSI_CMCR_GSR1TX | DSI_CMCR_GSR2TX | DSI_CMCR_GLWTX + | DSI_CMCR_DSW0TX | DSI_CMCR_DSW1TX | DSI_CMCR_DSR0TX | DSI_CMCR_DLWTX + | DSI_CMCR_MRDPS; + reg::DSI->GVCIDR = 0; + //// LTDC interface. + // Virtual channel for LTDC traffic. + reg::DSI->LVCIDR = 0; + // Color coding for the host and wrapper. + reg::DSI->LCOLCR = DSI_LCOLCR_COLC_24Bit; + reg::DSI->WCFGR = (reg::DSI->WCFGR & ~DSI_WCFGR_COLMUX) + | DSI_WCFGR_COLMUX_24Bit; + // Polarity of control signals. + reg::DSI->LPCR = 0; // HSP, VSP, DEP + reg::DSI->WCFGR |= 0; // VSPOL + //// Configure adapted command mode. + // Command mode. + reg::DSI->MCR |= DSI_MCR_CMDM; + reg::DSI->WCFGR |= DSI_WCFGR_DSIM; + // Maximum memory write. + reg::DSI->LCCR = width_; + // Tearing effect source and polarity, no automatic refresh. + reg::DSI->WCFGR &= ~(DSI_WCFGR_TESRC | DSI_WCFGR_AR); + // Tearing effect acknowledge. + reg::DSI->CMCR |= DSI_CMCR_TEARE; + //// Enable D-PHY and D-PHY clock lane settings. + reg::DSI->PCTLR = DSI_PCTLR_DEN; + reg::DSI->PCTLR = DSI_PCTLR_CKE | DSI_PCTLR_DEN; + //// Configure LTDC. + rcc_sai_pll_setup (8000000, + 4, // pllm => 8 MHz / 4 = 2 MHz + 208, // plln => 2 MHz * 208 = 416 MHz + 8, // pllp => 416 MHz / 8 = 52 MHz + 15, 32, // pllq, pllq_div => 416 MHz / 15 / 32 ~= 0.86 MHz + 5, 2); // pllr, pllr_div => 416 MHz / 5 / 2 ~= 41.6 MHz + Ltdc::enable (); + //// Enable DSI Host and DSI wrapper. + reg::DSI->CR = DSI_CR_EN; + reg::DSI->WCR = DSI_WCR_DSIEN; + //// Configure display. + config (); + //// Flow control & DBI interface. + reg::DSI->CMCR &= ~(DSI_CMCR_GSW0TX | DSI_CMCR_GSW1TX | DSI_CMCR_GSW2TX + | DSI_CMCR_GSR0TX | DSI_CMCR_GSR1TX | DSI_CMCR_GSR2TX + | DSI_CMCR_GLWTX | DSI_CMCR_DSW0TX | DSI_CMCR_DSW1TX + | DSI_CMCR_DSR0TX | DSI_CMCR_DLWTX | DSI_CMCR_MRDPS); + reg::DSI->PCR = DSI_PCR_BTAE; +} + +void +Dsi::disable () +{ + // TODO + reg::DSI->CR = 0; + reg::DSI->WCR = 0; + Ltdc::disable (); + rcc_peripheral_clock_disable (Rcc::DSI); +} + +void +Dsi::layer_setup (int layer, const Surface &surface, int x, int y) +{ + reg::DSI->WCR &= ~DSI_WCR_DSIEN; + Ltdc::layer_setup (layer, surface, x, y); + reg::DSI->WCR |= DSI_WCR_DSIEN; +} + +void +Dsi::refresh () +{ + ucoo::reg::DSI->WCR |= DSI_WCR_LTDCEN; +} + +void +Dsi::write_command (std::initializer_list data) +{ + while (!(reg::DSI->GPSR & DSI_GPSR_CMDFE)) + ; + uint32_t w = 0; + int wb = 0; + for (auto d : data) + { + w |= d << wb; + wb += 8; + if (wb == 32) + { + reg::DSI->GPDR = w; + w = 0; + wb = 0; + } + } + if (data.size () == 1) + { + reg::DSI->GHCR = DCS_SHORT_WRITE_PARAM_0 * DSI_GHCR_DT0 + | 0 * DSI_GHCR_VCID0 + | w * DSI_GHCR_WCLSB0; + } + else if (data.size () == 2) + { + reg::DSI->GHCR = DCS_SHORT_WRITE_PARAM_1 * DSI_GHCR_DT0 + | 0 * DSI_GHCR_VCID0 + | w * DSI_GHCR_WCLSB0; + } + else + { + if (wb) + reg::DSI->GPDR = w; + reg::DSI->GHCR = DCS_LONG_WRITE * DSI_GHCR_DT0 + | 0 * DSI_GHCR_VCID0 + | data.size () * DSI_GHCR_WCLSB0; + } +} + +} // namespace ucoo diff --git a/ucoo/hal/frame_buffer/dsi.stm32f4.hh b/ucoo/hal/frame_buffer/dsi.stm32f4.hh new file mode 100644 index 0000000..bb92d6d --- /dev/null +++ b/ucoo/hal/frame_buffer/dsi.stm32f4.hh @@ -0,0 +1,56 @@ +#ifndef ucoo_hal_frame_buffer_dsi_stm32f4_hh +#define ucoo_hal_frame_buffer_dsi_stm32f4_hh +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2016 Nicolas Schodet +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// }}} +#include "ucoo/hal/frame_buffer/ltdc.stm32f4.hh" +#include "ucoo/utils/function.hh" + +#include + +namespace ucoo { + +/// DSI controller, in Adapted Command mode. +class Dsi : public Ltdc +{ + public: + /// Constructor. + Dsi (int width, int heigth, int lanes); + /// Enable controller. + void enable (const Function &config); + /// Disable controller. + void disable (); + /// Setup a layer. + void layer_setup (int layer, const Surface &surface, int x, int y); + /// Refresh screen. + static void refresh (); + /// Write a command to display. + static void write_command (std::initializer_list data); + private: + /// Number of data lanes. + int lanes_; +}; + +} // namespace ucoo + +#endif // ucoo_hal_frame_buffer_dsi_stm32f4_hh diff --git a/ucoo/hal/frame_buffer/ltdc.stm32f4.cc b/ucoo/hal/frame_buffer/ltdc.stm32f4.cc new file mode 100644 index 0000000..4255ff7 --- /dev/null +++ b/ucoo/hal/frame_buffer/ltdc.stm32f4.cc @@ -0,0 +1,86 @@ +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2016 Nicolas Schodet +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// }}} +#include "ucoo/hal/frame_buffer/ltdc.stm32f4.hh" + +#include "ucoo/arch/reg.hh" +#include "ucoo/arch/rcc.stm32.hh" + +namespace ucoo { + +Ltdc::Ltdc (int width, int heigth, + int hsync, int hbp, int hfp, + int vsync, int vbp, int vfp) + : width_ (width), heigth_ (heigth), + hsync_ (hsync), hbp_ (hbp), hfp_ (hfp), + vsync_ (vsync), vbp_ (vbp), vfp_ (vfp) +{ +} + +void +Ltdc::enable () +{ + // TODO: make this more configurable. + // Enable clocks. + rcc_peripheral_clock_enable (Rcc::LTDC); + // Polarity of control signals. + reg::LTDC->GCR &= (LTDC_GCR_HSPOL | LTDC_GCR_VSPOL | LTDC_GCR_DEPOL + | LTDC_GCR_PCPOL); + // Timings. + reg::LTDC->SSCR = (hsync_ - 1) << 16 | (vsync_ - 1); + reg::LTDC->BPCR = (hsync_ + hbp_ - 1) << 16 | (vsync_ + vbp_ - 1); + reg::LTDC->AWCR = (hsync_ + hbp_ + width_ - 1) << 16 + | (vsync_ + vbp_ + heigth_ - 1); + reg::LTDC->TWCR = (hsync_ + hbp_ + width_ + hfp_ - 1) << 16 + | (vsync_ + vbp_ + heigth_ + vfp_ - 1); + // Enable. + reg::LTDC->GCR |= LTDC_GCR_LTDCEN; +} + +void +Ltdc::disable () +{ + reg::LTDC->GCR &= ~LTDC_GCR_LTDCEN; + rcc_peripheral_clock_disable (Rcc::LTDC); + // TODO: shut down PLL. +} + +void +Ltdc::layer_setup (int layer, const Surface &surface, int x, int y) +{ + auto reg = layer == 0 ? reg::LTDC_Layer1 : reg::LTDC_Layer2; + reg->WHPCR = (hsync_ + hbp_ + x + surface.w - 1) << 16 + | (hsync_ + hbp_ + x); + reg->WVPCR = (vsync_ + vbp_ + y + surface.h - 1) << 16 + | (vsync_ + vbp_ + y); + reg->PFCR = static_cast (surface.format) & 0xff; + reg->CFBAR = reinterpret_cast (surface.pixels); + reg->CFBLR = (surface.stride * surface.bpp () / 8) << 16 + | (surface.w * surface.bpp () / 8 + 3); + reg->CFBLNR = surface.h; + reg->CR = LTDC_LxCR_LEN; + // Load parameters. + reg::LTDC->SRCR = LTDC_SRCR_IMR; +} + +} // namespace ucoo diff --git a/ucoo/hal/frame_buffer/ltdc.stm32f4.hh b/ucoo/hal/frame_buffer/ltdc.stm32f4.hh new file mode 100644 index 0000000..edf95b0 --- /dev/null +++ b/ucoo/hal/frame_buffer/ltdc.stm32f4.hh @@ -0,0 +1,53 @@ +#ifndef ucoo_hal_frame_buffer_ltdc_stm32f4_hh +#define ucoo_hal_frame_buffer_ltdc_stm32f4_hh +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2016 Nicolas Schodet +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// }}} +#include "ucoo/intf/frame_buffer.hh" + +namespace ucoo { + +/// LTDC controller. +class Ltdc +{ + public: + /// Constructor, take timing parameters. + Ltdc (int width, int heigth, + int hsync, int hbp, int hfp, + int vsync, int vbp, int vfp); + /// Enable controller. + void enable (); + /// Disable controller. + void disable (); + /// Setup a layer. + void layer_setup (int layer, const Surface &surface, int x, int y); + protected: + int width_, heigth_; + private: + int hsync_, hbp_, hfp_; + int vsync_, vbp_, vfp_; +}; + +} // namespace ucoo + +#endif // ucoo_hal_frame_buffer_ltdc_stm32f4_hh -- cgit v1.2.3