added prescaler for 16 bit pwm in LPC1347 target
Fork of mbed-dev by
Diff: targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_ebi.c
- Revision:
- 144:ef7eb2e8f9f7
- Parent:
- 50:a417edff4437
--- a/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_ebi.c Tue Aug 02 14:07:36 2016 +0000 +++ b/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_ebi.c Fri Sep 02 15:07:44 2016 +0100 @@ -1,1187 +1,1187 @@ -/***************************************************************************//** - * @file em_ebi.c - * @brief External Bus Interface (EBI) Peripheral API - * @version 4.2.1 - ******************************************************************************* - * @section License - * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b> - ******************************************************************************* - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no - * obligation to support this Software. Silicon Labs is providing the - * Software "AS IS", with no express or implied warranties of any kind, - * including, but not limited to, any implied warranties of merchantability - * or fitness for any particular purpose or warranties against infringement - * of any proprietary rights of a third party. - * - * Silicon Labs will not be liable for any consequential, incidental, or - * special damages, or any other relief, or for any claim by any third party, - * arising from your use of this Software. - * - ******************************************************************************/ - -#include "em_ebi.h" -#if defined(EBI_COUNT) && (EBI_COUNT > 0) -#include "em_assert.h" -#include "em_bus.h" - -/***************************************************************************//** - * @addtogroup EM_Library - * @{ - ******************************************************************************/ - -/***************************************************************************//** - * @addtogroup EBI - * @brief EBI External Bus Interface (EBI) Peripheral API - * @{ - ******************************************************************************/ - -/***************************************************************************//** - * @brief - * Configure and enable External Bus Interface - * - * @param[in] ebiInit - * EBI configuration structure - * - * @note - * GPIO lines must be configured as PUSH_PULL for correct operation - * GPIO and EBI clocks must be enabled in the CMU - ******************************************************************************/ -void EBI_Init(const EBI_Init_TypeDef *ebiInit) -{ - uint32_t ctrl = EBI->CTRL; - -#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) - /* Enable Independent Timing for devices that supports it */ - ctrl |= EBI_CTRL_ITS; - - /* Set polarity of address ready */ - EBI_BankPolaritySet(ebiInit->banks, ebiLineARDY, ebiInit->ardyPolarity); - /* Set polarity of address latch enable */ - EBI_BankPolaritySet(ebiInit->banks, ebiLineALE, ebiInit->alePolarity); - /* Set polarity of write enable */ - EBI_BankPolaritySet(ebiInit->banks, ebiLineWE, ebiInit->wePolarity); - /* Set polarity of read enable */ - EBI_BankPolaritySet(ebiInit->banks, ebiLineRE, ebiInit->rePolarity); - /* Set polarity of chip select lines */ - EBI_BankPolaritySet(ebiInit->banks, ebiLineCS, ebiInit->csPolarity); - /* Set polarity of byte lane line */ - EBI_BankPolaritySet(ebiInit->banks, ebiLineBL, ebiInit->blPolarity); -#else - /* Set polarity of address ready */ - EBI_PolaritySet(ebiLineARDY, ebiInit->ardyPolarity); - /* Set polarity of address latch enable */ - EBI_PolaritySet(ebiLineALE, ebiInit->alePolarity); - /* Set polarity of write enable */ - EBI_PolaritySet(ebiLineWE, ebiInit->wePolarity); - /* Set polarity of read enable */ - EBI_PolaritySet(ebiLineRE, ebiInit->rePolarity); - /* Set polarity of chip select lines */ - EBI_PolaritySet(ebiLineCS, ebiInit->csPolarity); -#endif - - /* Configure EBI mode and control settings */ -#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) - if (ebiInit->banks & EBI_BANK0) - { - ctrl &= ~(_EBI_CTRL_MODE_MASK - | _EBI_CTRL_ARDYEN_MASK - | _EBI_CTRL_ARDYTODIS_MASK - | _EBI_CTRL_BL_MASK - | _EBI_CTRL_NOIDLE_MASK - | _EBI_CTRL_BANK0EN_MASK); - ctrl |= (ebiInit->mode << _EBI_CTRL_MODE_SHIFT); - ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDYEN_SHIFT); - ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTODIS_SHIFT); - ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL_SHIFT); - ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE_SHIFT); - if ( ebiInit->enable) - { - ctrl |= EBI_CTRL_BANK0EN; - } - } - if (ebiInit->banks & EBI_BANK1) - { - ctrl &= ~(_EBI_CTRL_BL1_MASK - | _EBI_CTRL_MODE1_MASK - | _EBI_CTRL_ARDY1EN_MASK - | _EBI_CTRL_ARDYTO1DIS_MASK - | _EBI_CTRL_NOIDLE1_MASK - | _EBI_CTRL_BANK1EN_MASK); - ctrl |= (ebiInit->mode << _EBI_CTRL_MODE1_SHIFT); - ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY1EN_SHIFT); - ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO1DIS_SHIFT); - ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL1_SHIFT); - ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE1_SHIFT); - if ( ebiInit->enable) - { - ctrl |= EBI_CTRL_BANK1EN; - } - } - if (ebiInit->banks & EBI_BANK2) - { - ctrl &= ~(_EBI_CTRL_BL2_MASK - | _EBI_CTRL_MODE2_MASK - | _EBI_CTRL_ARDY2EN_MASK - | _EBI_CTRL_ARDYTO2DIS_MASK - | _EBI_CTRL_NOIDLE2_MASK - | _EBI_CTRL_BANK2EN_MASK); - ctrl |= (ebiInit->mode << _EBI_CTRL_MODE2_SHIFT); - ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY2EN_SHIFT); - ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO2DIS_SHIFT); - ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL2_SHIFT); - ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE2_SHIFT); - if ( ebiInit->enable) - { - ctrl |= EBI_CTRL_BANK2EN; - } - } - if (ebiInit->banks & EBI_BANK3) - { - ctrl &= ~(_EBI_CTRL_BL3_MASK - | _EBI_CTRL_MODE3_MASK - | _EBI_CTRL_ARDY3EN_MASK - | _EBI_CTRL_ARDYTO3DIS_MASK - | _EBI_CTRL_NOIDLE3_MASK - | _EBI_CTRL_BANK3EN_MASK); - ctrl |= (ebiInit->mode << _EBI_CTRL_MODE3_SHIFT); - ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY3EN_SHIFT); - ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO3DIS_SHIFT); - ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL3_SHIFT); - ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE3_SHIFT); - if ( ebiInit->enable) - { - ctrl |= EBI_CTRL_BANK3EN; - } - } -#else - ctrl &= ~(_EBI_CTRL_MODE_MASK - | _EBI_CTRL_ARDYEN_MASK - | _EBI_CTRL_ARDYTODIS_MASK - | _EBI_CTRL_BANK0EN_MASK - | _EBI_CTRL_BANK1EN_MASK - | _EBI_CTRL_BANK2EN_MASK - | _EBI_CTRL_BANK3EN_MASK); - if ( ebiInit->enable) - { - if ( ebiInit->banks & EBI_BANK0 ) - { - ctrl |= EBI_CTRL_BANK0EN; - } - if ( ebiInit->banks & EBI_BANK1 ) - { - ctrl |= EBI_CTRL_BANK1EN; - } - if ( ebiInit->banks & EBI_BANK2 ) - { - ctrl |= EBI_CTRL_BANK2EN; - } - if ( ebiInit->banks & EBI_BANK3 ) - { - ctrl |= EBI_CTRL_BANK3EN; - } - } - ctrl |= ebiInit->mode; - ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDYEN_SHIFT); - ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTODIS_SHIFT); -#endif - - /* Configure timing */ -#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) - EBI_BankReadTimingSet(ebiInit->banks, - ebiInit->readSetupCycles, - ebiInit->readStrobeCycles, - ebiInit->readHoldCycles); - EBI_BankReadTimingConfig(ebiInit->banks, - ebiInit->readPageMode, - ebiInit->readPrefetch, - ebiInit->readHalfRE); - EBI_BankWriteTimingSet(ebiInit->banks, - ebiInit->writeSetupCycles, - ebiInit->writeStrobeCycles, - ebiInit->writeHoldCycles); - EBI_BankWriteTimingConfig(ebiInit->banks, - ebiInit->writeBufferDisable, - ebiInit->writeHalfWE); - EBI_BankAddressTimingSet(ebiInit->banks, - ebiInit->addrSetupCycles, - ebiInit->addrHoldCycles); - EBI_BankAddressTimingConfig(ebiInit->banks, - ebiInit->addrHalfALE); -#else - EBI_ReadTimingSet(ebiInit->readSetupCycles, - ebiInit->readStrobeCycles, - ebiInit->readHoldCycles); - EBI_WriteTimingSet(ebiInit->writeSetupCycles, - ebiInit->writeStrobeCycles, - ebiInit->writeHoldCycles); - EBI_AddressTimingSet(ebiInit->addrSetupCycles, - ebiInit->addrHoldCycles); -#endif - - /* Activate new configuration */ - EBI->CTRL = ctrl; - - /* Configure Adress Latch Enable */ - switch (ebiInit->mode) - { - case ebiModeD16A16ALE: - case ebiModeD8A24ALE: - /* Address Latch Enable */ - BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_ALEPEN_SHIFT, 1); - break; -#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) - case ebiModeD16: -#endif - case ebiModeD8A8: - /* Make sure Address Latch is disabled */ - BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_ALEPEN_SHIFT, 0); - break; - } -#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) - /* Limit pin enable */ - EBI->ROUTE = (EBI->ROUTE & ~_EBI_ROUTE_ALB_MASK) | ebiInit->aLow; - EBI->ROUTE = (EBI->ROUTE & ~_EBI_ROUTE_APEN_MASK) | ebiInit->aHigh; - /* Location */ - EBI->ROUTE = (EBI->ROUTE & ~_EBI_ROUTE_LOCATION_MASK) | ebiInit->location; - - /* Enable EBI BL pin if necessary */ - if(ctrl & (_EBI_CTRL_BL_MASK|_EBI_CTRL_BL1_MASK|_EBI_CTRL_BL2_MASK|_EBI_CTRL_BL3_MASK)) - { - BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_BLPEN_SHIFT, ebiInit->blEnable); - } -#endif - /* Enable EBI pins EBI_WEn and EBI_REn */ - BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_EBIPEN_SHIFT, 1); - - /* Enable chip select lines */ - EBI_ChipSelectEnable(ebiInit->csLines, true); -} - - -/***************************************************************************//** - * @brief - * Disable External Bus Interface - ******************************************************************************/ -void EBI_Disable(void) -{ - /* Disable pins */ - EBI->ROUTE = _EBI_ROUTE_RESETVALUE; - /* Disable banks */ - EBI->CTRL = _EBI_CTRL_RESETVALUE; -} - - -/***************************************************************************//** - * @brief - * Enable or disable EBI Bank - * - * @param[in] banks - * Banks to reconfigure, mask of EBI_BANK<n> flags - * - * @param[in] enable - * True to enable, false to disable - ******************************************************************************/ -void EBI_BankEnable(uint32_t banks, bool enable) -{ - if (banks & EBI_BANK0) - { - BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK0EN_SHIFT, enable); - } - if (banks & EBI_BANK1) - { - BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK1EN_SHIFT, enable); - } - if (banks & EBI_BANK2) - { - BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK2EN_SHIFT, enable); - } - if (banks & EBI_BANK3) - { - BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK3EN_SHIFT, enable); - } -} - - -/***************************************************************************//** - * @brief - * Return base address of EBI bank - * - * @param[in] bank - * Bank to return start address for - * - * @return - * Absolute address of bank - ******************************************************************************/ -uint32_t EBI_BankAddress(uint32_t bank) -{ -#if defined (_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) - if(EBI->CTRL & EBI_CTRL_ALTMAP) - { - switch (bank) - { - case EBI_BANK0: - return(EBI_MEM_BASE); - - case EBI_BANK1: - return(EBI_MEM_BASE + 0x10000000UL); - - case EBI_BANK2: - return(EBI_MEM_BASE + 0x20000000UL); - - case EBI_BANK3: - return(EBI_MEM_BASE + 0x30000000UL); - - default: - EFM_ASSERT(0); - break; - } - } -#endif - switch (bank) - { - case EBI_BANK0: - return(EBI_MEM_BASE); - - case EBI_BANK1: - return(EBI_MEM_BASE + 0x04000000UL); - - case EBI_BANK2: - return(EBI_MEM_BASE + 0x08000000UL); - - case EBI_BANK3: - return(EBI_MEM_BASE + 0x0C000000UL); - - default: - EFM_ASSERT(0); - break; - } - return 0; -} - - -/***************************************************************************//** - * @brief - * Enable or disable EBI Chip Select - * - * @param[in] cs - * ChipSelect lines to reconfigure, mask of EBI_CS<n> flags - * - * @param[in] enable - * True to enable, false to disable - ******************************************************************************/ -void EBI_ChipSelectEnable(uint32_t cs, bool enable) -{ - if (cs & EBI_CS0) - { - BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_CS0PEN_SHIFT, enable); - } - if (cs & EBI_CS1) - { - BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_CS1PEN_SHIFT, enable); - } - if (cs & EBI_CS2) - { - BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_CS2PEN_SHIFT, enable); - } - if (cs & EBI_CS3) - { - BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_CS3PEN_SHIFT, enable); - } -} - - -/***************************************************************************//** - * @brief - * Configure EBI pin polarity - * - * @param[in] line - * Which pin/line to configure - * - * @param[in] polarity - * Active high, or active low - ******************************************************************************/ -void EBI_PolaritySet(EBI_Line_TypeDef line, EBI_Polarity_TypeDef polarity) -{ - switch (line) - { - case ebiLineARDY: - BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_ARDYPOL_SHIFT, polarity); - break; - case ebiLineALE: - BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_ALEPOL_SHIFT, polarity); - break; - case ebiLineWE: - BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_WEPOL_SHIFT, polarity); - break; - case ebiLineRE: - BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_REPOL_SHIFT, polarity); - break; - case ebiLineCS: - BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_CSPOL_SHIFT, polarity); - break; -#if defined (_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) - case ebiLineBL: - BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_BLPOL_SHIFT, polarity); - break; - case ebiLineTFTVSync: - BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_VSYNCPOL_SHIFT, polarity); - break; - case ebiLineTFTHSync: - BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_HSYNCPOL_SHIFT, polarity); - break; - case ebiLineTFTDataEn: - BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DATAENPOL_SHIFT, polarity); - break; - case ebiLineTFTDClk: - BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DCLKPOL_SHIFT, polarity); - break; - case ebiLineTFTCS: - BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_CSPOL_SHIFT, polarity); - break; -#endif - default: - EFM_ASSERT(0); - break; - } -} - - -/***************************************************************************//** - * @brief - * Configure timing values of read bus accesses - * - * @param[in] setupCycles - * Number of clock cycles for address setup before REn is asserted - * - * @param[in] strobeCycles - * The number of cycles the REn is held active. After the specified number of - * cycles, data is read. If set to 0, 1 cycle is inserted by HW - * - * @param[in] holdCycles - * The number of cycles CSn is held active after the REn is dessarted - ******************************************************************************/ -void EBI_ReadTimingSet(int setupCycles, int strobeCycles, int holdCycles) -{ - uint32_t readTiming; - - /* Check that timings are within limits */ - EFM_ASSERT(setupCycles < 4); - EFM_ASSERT(strobeCycles < 16); - EFM_ASSERT(holdCycles < 4); - - /* Configure timing values */ - readTiming = (setupCycles << _EBI_RDTIMING_RDSETUP_SHIFT) - | (strobeCycles << _EBI_RDTIMING_RDSTRB_SHIFT) - | (holdCycles << _EBI_RDTIMING_RDHOLD_SHIFT); - - - EBI->RDTIMING = (EBI->RDTIMING - & ~(_EBI_RDTIMING_RDSETUP_MASK - | _EBI_RDTIMING_RDSTRB_MASK - | _EBI_RDTIMING_RDHOLD_MASK)) - | readTiming; -} - - -/***************************************************************************//** - * @brief - * Configure timing values of write bus accesses - * - * @param[in] setupCycles - * Number of clock cycles for address setup before WEn is asserted - * - * @param[in] strobeCycles - * Number of cycles WEn is held active. If set to 0, 1 cycle is inserted by HW - * - * @param[in] holdCycles - * Number of cycles CSn is held active after the WEn is deasserted - ******************************************************************************/ -void EBI_WriteTimingSet(int setupCycles, int strobeCycles, int holdCycles) -{ - uint32_t writeTiming; - - /* Check that timings are within limits */ - EFM_ASSERT(setupCycles < 4); - EFM_ASSERT(strobeCycles < 16); - EFM_ASSERT(holdCycles < 4); - - /* Configure timing values */ - writeTiming = (setupCycles << _EBI_WRTIMING_WRSETUP_SHIFT) - | (strobeCycles << _EBI_WRTIMING_WRSTRB_SHIFT) - | (holdCycles << _EBI_WRTIMING_WRHOLD_SHIFT); - - EBI->WRTIMING = (EBI->WRTIMING - & ~(_EBI_WRTIMING_WRSETUP_MASK - | _EBI_WRTIMING_WRSTRB_MASK - | _EBI_WRTIMING_WRHOLD_MASK)) - | writeTiming; -} - - -/***************************************************************************//** - * @brief - * Configure timing values of address latch bus accesses - * - * @param[in] setupCycles - * Sets the number of cycles the address is held after ALE is asserted - * - * @param[in] holdCycles - * Sets the number of cycles the address is driven onto the ADDRDAT bus before - * ALE is asserted. If set 0, 1 cycle is inserted by HW - ******************************************************************************/ -void EBI_AddressTimingSet(int setupCycles, int holdCycles) -{ - uint32_t addressLatchTiming; - - /* Check that timing values are within limits */ - EFM_ASSERT(setupCycles < 4); - EFM_ASSERT(holdCycles < 4); - - /* Configure address latch timing values */ - addressLatchTiming = (setupCycles << _EBI_ADDRTIMING_ADDRSETUP_SHIFT) - | (holdCycles << _EBI_ADDRTIMING_ADDRHOLD_SHIFT); - - EBI->ADDRTIMING = (EBI->ADDRTIMING - & ~(_EBI_ADDRTIMING_ADDRSETUP_MASK - | _EBI_ADDRTIMING_ADDRHOLD_MASK)) - | addressLatchTiming; -} - -#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) -/***************************************************************************//** - * @brief - * Configure and initialize TFT Direct Drive - * - * @param[in] ebiTFTInit - * TFT Initialization structure - ******************************************************************************/ -void EBI_TFTInit(const EBI_TFTInit_TypeDef *ebiTFTInit) -{ - uint32_t ctrl; - - /* Configure base address for frame buffer offset to EBI bank */ - EBI_TFTFrameBaseSet(ebiTFTInit->addressOffset); - - /* Configure display size and porch areas */ - EBI_TFTSizeSet(ebiTFTInit->hsize, - ebiTFTInit->vsize); - EBI_TFTHPorchSet(ebiTFTInit->hPorchFront, - ebiTFTInit->hPorchBack, - ebiTFTInit->hPulseWidth); - EBI_TFTVPorchSet(ebiTFTInit->vPorchFront, - ebiTFTInit->vPorchBack, - ebiTFTInit->vPulseWidth); - - /* Configure timing settings */ - EBI_TFTTimingSet(ebiTFTInit->dclkPeriod, - ebiTFTInit->startPosition, - ebiTFTInit->setupCycles, - ebiTFTInit->holdCycles); - - /* Configure line polarity settings */ - EBI_PolaritySet(ebiLineTFTCS, ebiTFTInit->csPolarity); - EBI_PolaritySet(ebiLineTFTDClk, ebiTFTInit->dclkPolarity); - EBI_PolaritySet(ebiLineTFTDataEn, ebiTFTInit->dataenPolarity); - EBI_PolaritySet(ebiLineTFTVSync, ebiTFTInit->vsyncPolarity); - EBI_PolaritySet(ebiLineTFTHSync, ebiTFTInit->hsyncPolarity); - - /* Main control, EBI bank select, mask and blending configuration */ - ctrl = (uint32_t)ebiTFTInit->bank - | (uint32_t)ebiTFTInit->width - | (uint32_t)ebiTFTInit->colSrc - | (uint32_t)ebiTFTInit->interleave - | (uint32_t)ebiTFTInit->fbTrigger - | (uint32_t)(ebiTFTInit->shiftDClk == true - ? (1 << _EBI_TFTCTRL_SHIFTDCLKEN_SHIFT) : 0) - | (uint32_t)ebiTFTInit->maskBlend - | (uint32_t)ebiTFTInit->driveMode; - - EBI->TFTCTRL = ctrl; - - /* Enable TFT pins */ - if (ebiTFTInit->driveMode != ebiTFTDDModeDisabled) - { - EBI->ROUTE |= EBI_ROUTE_TFTPEN; - } -} - - -/***************************************************************************//** - * @brief - * Configure and initialize TFT size settings - * - * @param[in] horizontal - * TFT display horizontal size in pixels - * @param[in] vertical - * TFT display vertical size in pixels - ******************************************************************************/ -void EBI_TFTSizeSet(uint32_t horizontal, uint32_t vertical) -{ - EFM_ASSERT((horizontal-1) < 1024); - EFM_ASSERT((vertical-1) < 1024); - - EBI->TFTSIZE = ((horizontal-1) << _EBI_TFTSIZE_HSZ_SHIFT) - | ((vertical-1) << _EBI_TFTSIZE_VSZ_SHIFT); -} - -/***************************************************************************//** - * @brief - * Configure and initialize Horizontal Porch Settings - * - * @param[in] front - * Horizontal front porch size in pixels - * @param[in] back - * Horizontal back porch size in pixels - * @param[in] pulseWidth - * Horizontal synchronization pulse width. Set to required -1. - ******************************************************************************/ -void EBI_TFTHPorchSet(int front, int back, int pulseWidth) -{ - EFM_ASSERT(front < 256); - EFM_ASSERT(back < 256); - EFM_ASSERT((pulseWidth-1) < 128); - - EBI->TFTHPORCH = (front << _EBI_TFTHPORCH_HFPORCH_SHIFT) - | (back << _EBI_TFTHPORCH_HBPORCH_SHIFT) - | ((pulseWidth-1) << _EBI_TFTHPORCH_HSYNC_SHIFT); -} - - -/***************************************************************************//** - * @brief - * Configure Vertical Porch Settings - * - * @param[in] front - * Vertical front porch size in pixels - * @param[in] back - * Vertical back porch size in pixels - * @param[in] pulseWidth - * Vertical synchronization pulse width. Set to required -1. - ******************************************************************************/ -void EBI_TFTVPorchSet(int front, int back, int pulseWidth) -{ - EFM_ASSERT(front < 256); - EFM_ASSERT(back < 256); - EFM_ASSERT((pulseWidth-1) < 128); - - EBI->TFTVPORCH = (front << _EBI_TFTVPORCH_VFPORCH_SHIFT) - | (back << _EBI_TFTVPORCH_VBPORCH_SHIFT) - | ((pulseWidth-1) << _EBI_TFTVPORCH_VSYNC_SHIFT); -} - - -/***************************************************************************//** - * @brief - * Configure TFT Direct Drive Timing Settings - * - * @param[in] dclkPeriod - * DCLK period in internal cycles - * - * @param[in] start - * Starting position of external direct drive, relative to DCLK inactive edge - * - * @param[in] setup - * Number of cycles RGB data is driven before active edge of DCLK - * - * @param[in] hold - * Number of cycles RGB data is held after active edge of DCLK - ******************************************************************************/ -void EBI_TFTTimingSet(int dclkPeriod, int start, int setup, int hold) -{ - EFM_ASSERT(dclkPeriod < 2048); - EFM_ASSERT(start < 2048); - EFM_ASSERT(setup < 4); - EFM_ASSERT(hold < 4); - - EBI->TFTTIMING = (dclkPeriod << _EBI_TFTTIMING_DCLKPERIOD_SHIFT) - | (start << _EBI_TFTTIMING_TFTSTART_SHIFT) - | (setup << _EBI_TFTTIMING_TFTSETUP_SHIFT) - | (hold << _EBI_TFTTIMING_TFTHOLD_SHIFT); -} -#endif - -#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) -/***************************************************************************//** - * @brief - * Configure read operation parameters for selected bank - * - * @param[in] banks - * Mask of memory bank(s) to configure write timing for - * - * @param[in] pageMode - * Enables or disables half cycle WE strobe in last strobe cycle - * - * @param[in] prefetch - * Enables or disables half cycle WE strobe in last strobe cycle - * - * @param[in] halfRE - * Enables or disables half cycle WE strobe in last strobe cycle - ******************************************************************************/ -void EBI_BankReadTimingConfig(uint32_t banks, bool pageMode, bool prefetch, bool halfRE) -{ - /* Verify only valid banks are used */ - EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); - - /* Configure read operation parameters */ - if( banks & EBI_BANK0 ) - { - BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); - BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); - BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_HALFRE_SHIFT, halfRE); - } - if( banks & EBI_BANK1 ) - { - BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); - BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); - BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_HALFRE_SHIFT, halfRE); - } - if( banks & EBI_BANK2 ) - { - BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); - BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); - BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_HALFRE_SHIFT, halfRE); - } - if( banks & EBI_BANK3 ) - { - BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); - BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); - BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_HALFRE_SHIFT, halfRE); - } -} - -/***************************************************************************//** - * @brief - * Configure timing values of read bus accesses - * - * @param[in] banks - * Mask of memory bank(s) to configure timing for - * - * @param[in] setupCycles - * Number of clock cycles for address setup before REn is asserted - * - * @param[in] strobeCycles - * The number of cycles the REn is held active. After the specified number of - * cycles, data is read. If set to 0, 1 cycle is inserted by HW - * - * @param[in] holdCycles - * The number of cycles CSn is held active after the REn is dessarted - ******************************************************************************/ -void EBI_BankReadTimingSet(uint32_t banks, int setupCycles, int strobeCycles, int holdCycles) -{ - uint32_t readTiming; - - /* Verify only valid banks are used */ - EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); - - /* Check that timings are within limits */ - EFM_ASSERT(setupCycles < 4); - EFM_ASSERT(strobeCycles < 64); - EFM_ASSERT(holdCycles < 4); - - /* Configure timing values */ - readTiming = (setupCycles << _EBI_RDTIMING_RDSETUP_SHIFT) - | (strobeCycles << _EBI_RDTIMING_RDSTRB_SHIFT) - | (holdCycles << _EBI_RDTIMING_RDHOLD_SHIFT); - - if (banks & EBI_BANK0) - { - EBI->RDTIMING = (EBI->RDTIMING - & ~(_EBI_RDTIMING_RDSETUP_MASK - | _EBI_RDTIMING_RDSTRB_MASK - | _EBI_RDTIMING_RDHOLD_MASK)) - | readTiming; - } - if (banks & EBI_BANK1) - { - EBI->RDTIMING1 = (EBI->RDTIMING1 - & ~(_EBI_RDTIMING1_RDSETUP_MASK - | _EBI_RDTIMING1_RDSTRB_MASK - | _EBI_RDTIMING1_RDHOLD_MASK)) - | readTiming; - } - if (banks & EBI_BANK2) - { - EBI->RDTIMING2 = (EBI->RDTIMING2 - & ~(_EBI_RDTIMING2_RDSETUP_MASK - | _EBI_RDTIMING2_RDSTRB_MASK - | _EBI_RDTIMING2_RDHOLD_MASK)) - | readTiming; - } - if (banks & EBI_BANK3) - { - EBI->RDTIMING3 = (EBI->RDTIMING3 - & ~(_EBI_RDTIMING3_RDSETUP_MASK - | _EBI_RDTIMING3_RDSTRB_MASK - | _EBI_RDTIMING3_RDHOLD_MASK)) - | readTiming; - } -} - - -/***************************************************************************//** - * @brief - * Configure write operation parameters for selected bank - * - * @param[in] banks - * Mask of memory bank(s) to configure write timing for - * - * @param[in] writeBufDisable - * If true, disable the write buffer - * - * @param[in] halfWE - * Enables or disables half cycle WE strobe in last strobe cycle - ******************************************************************************/ -void EBI_BankWriteTimingConfig(uint32_t banks, bool writeBufDisable, bool halfWE) -{ - /* Verify only valid banks are used */ - EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); - - /* Configure write operation parameters */ - if( banks & EBI_BANK0 ) - { - BUS_RegBitWrite(&EBI->WRTIMING, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); - BUS_RegBitWrite(&EBI->WRTIMING, _EBI_WRTIMING_HALFWE_SHIFT, halfWE); - } - if( banks & EBI_BANK1 ) - { - BUS_RegBitWrite(&EBI->WRTIMING1, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); - BUS_RegBitWrite(&EBI->WRTIMING1, _EBI_WRTIMING_HALFWE_SHIFT, halfWE); - } - if( banks & EBI_BANK2 ) - { - BUS_RegBitWrite(&EBI->WRTIMING2, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); - BUS_RegBitWrite(&EBI->WRTIMING2, _EBI_WRTIMING_HALFWE_SHIFT, halfWE); - } - if( banks & EBI_BANK3 ) - { - BUS_RegBitWrite(&EBI->WRTIMING3, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); - BUS_RegBitWrite(&EBI->WRTIMING3, _EBI_WRTIMING_HALFWE_SHIFT, halfWE); - } -} - - -/***************************************************************************//** - * @brief - * Configure timing values of write bus accesses - * - * @param[in] banks - * Mask of memory bank(s) to configure write timing for - * - * @param[in] setupCycles - * Number of clock cycles for address setup before WEn is asserted - * - * @param[in] strobeCycles - * Number of cycles WEn is held active. If set to 0, 1 cycle is inserted by HW - * - * @param[in] holdCycles - * Number of cycles CSn is held active after the WEn is deasserted - ******************************************************************************/ -void EBI_BankWriteTimingSet(uint32_t banks, int setupCycles, int strobeCycles, int holdCycles) -{ - uint32_t writeTiming; - - /* Verify only valid banks are used */ - EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); - - /* Check that timings are within limits */ - EFM_ASSERT(setupCycles < 4); - EFM_ASSERT(strobeCycles < 64); - EFM_ASSERT(holdCycles < 4); - - /* Configure timing values */ - writeTiming = (setupCycles << _EBI_WRTIMING_WRSETUP_SHIFT) - | (strobeCycles << _EBI_WRTIMING_WRSTRB_SHIFT) - | (holdCycles << _EBI_WRTIMING_WRHOLD_SHIFT); - - if (banks & EBI_BANK0) - { - EBI->WRTIMING = (EBI->WRTIMING - & ~(_EBI_WRTIMING_WRSETUP_MASK - | _EBI_WRTIMING_WRSTRB_MASK - | _EBI_WRTIMING_WRHOLD_MASK)) - | writeTiming; - } - if (banks & EBI_BANK1) - { - EBI->WRTIMING1 = (EBI->WRTIMING1 - & ~(_EBI_WRTIMING1_WRSETUP_MASK - | _EBI_WRTIMING1_WRSTRB_MASK - | _EBI_WRTIMING1_WRHOLD_MASK)) - | writeTiming; - } - if (banks & EBI_BANK2) - { - EBI->WRTIMING2 = (EBI->WRTIMING2 - & ~(_EBI_WRTIMING2_WRSETUP_MASK - | _EBI_WRTIMING2_WRSTRB_MASK - | _EBI_WRTIMING2_WRHOLD_MASK)) - | writeTiming; - } - if (banks & EBI_BANK3) - { - EBI->WRTIMING3 = (EBI->WRTIMING3 - & ~(_EBI_WRTIMING3_WRSETUP_MASK - | _EBI_WRTIMING3_WRSTRB_MASK - | _EBI_WRTIMING3_WRHOLD_MASK)) - | writeTiming; - } -} - - -/***************************************************************************//** - * @brief - * Configure address operation parameters for selected bank - * - * @param[in] banks - * Mask of memory bank(s) to configure write timing for - * - * @param[in] halfALE - * Enables or disables half cycle ALE strobe in last strobe cycle - ******************************************************************************/ -void EBI_BankAddressTimingConfig(uint32_t banks, bool halfALE) -{ - /* Verify only valid banks are used */ - EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); - - if( banks & EBI_BANK0 ) - { - BUS_RegBitWrite(&EBI->ADDRTIMING, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE); - } - if( banks & EBI_BANK1 ) - { - BUS_RegBitWrite(&EBI->ADDRTIMING1, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE); - } - if( banks & EBI_BANK2 ) - { - BUS_RegBitWrite(&EBI->ADDRTIMING2, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE); - } - if( banks & EBI_BANK3 ) - { - BUS_RegBitWrite(&EBI->ADDRTIMING3, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE); - } -} - - -/***************************************************************************//** - * @brief - * Configure timing values of address latch bus accesses - * - * @param[in] banks - * Mask of memory bank(s) to configure address timing for - * - * @param[in] setupCycles - * Sets the number of cycles the address is held after ALE is asserted - * - * @param[in] holdCycles - * Sets the number of cycles the address is driven onto the ADDRDAT bus before - * ALE is asserted. If set 0, 1 cycle is inserted by HW - ******************************************************************************/ -void EBI_BankAddressTimingSet(uint32_t banks, int setupCycles, int holdCycles) -{ - uint32_t addressLatchTiming; - - /* Verify only valid banks are used */ - EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); - - /* Check that timing values are within limits */ - EFM_ASSERT(setupCycles < 4); - EFM_ASSERT(holdCycles < 4); - - /* Configure address latch timing values */ - addressLatchTiming = (setupCycles << _EBI_ADDRTIMING_ADDRSETUP_SHIFT) - | (holdCycles << _EBI_ADDRTIMING_ADDRHOLD_SHIFT); - - if (banks & EBI_BANK0) - { - EBI->ADDRTIMING = (EBI->ADDRTIMING - & ~(_EBI_ADDRTIMING_ADDRSETUP_MASK - | _EBI_ADDRTIMING_ADDRHOLD_MASK)) - | addressLatchTiming; - } - if (banks & EBI_BANK1) - { - EBI->ADDRTIMING1 = (EBI->ADDRTIMING1 - & ~(_EBI_ADDRTIMING1_ADDRSETUP_MASK - | _EBI_ADDRTIMING1_ADDRHOLD_MASK)) - | addressLatchTiming; - } - if (banks & EBI_BANK2) - { - EBI->ADDRTIMING2 = (EBI->ADDRTIMING2 - & ~(_EBI_ADDRTIMING2_ADDRSETUP_MASK - | _EBI_ADDRTIMING2_ADDRHOLD_MASK)) - | addressLatchTiming; - } - if (banks & EBI_BANK3) - { - EBI->ADDRTIMING3 = (EBI->ADDRTIMING3 - & ~(_EBI_ADDRTIMING3_ADDRSETUP_MASK - | _EBI_ADDRTIMING3_ADDRHOLD_MASK)) - | addressLatchTiming; - } -} - - -/***************************************************************************//** - * @brief - * Configure EBI pin polarity for selected bank(s) for devices with individual - * timing support - * - * @param[in] banks - * Mask of memory bank(s) to configure polarity for - * - * @param[in] line - * Which pin/line to configure - * - * @param[in] polarity - * Active high, or active low - ******************************************************************************/ -void EBI_BankPolaritySet(uint32_t banks, EBI_Line_TypeDef line, EBI_Polarity_TypeDef polarity) -{ - uint32_t bankSet = 0; - volatile uint32_t *polRegister = 0; - - /* Verify only valid banks are used */ - EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); - - while (banks) - { -#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) - if (banks & EBI_BANK0) - { - polRegister = &EBI->POLARITY; - bankSet = EBI_BANK0; - } - if (banks & EBI_BANK1) - { - polRegister = &EBI->POLARITY1; - bankSet = EBI_BANK1; - } - if (banks & EBI_BANK2) - { - polRegister = &EBI->POLARITY2; - bankSet = EBI_BANK2; - } - if (banks & EBI_BANK3) - { - polRegister = &EBI->POLARITY3; - bankSet = EBI_BANK3; - } -#else - polRegister = &EBI->POLARITY; - banks = 0; -#endif - - /* What line to configure */ - switch (line) - { - case ebiLineARDY: - BUS_RegBitWrite(polRegister, _EBI_POLARITY_ARDYPOL_SHIFT, polarity); - break; - case ebiLineALE: - BUS_RegBitWrite(polRegister, _EBI_POLARITY_ALEPOL_SHIFT, polarity); - break; - case ebiLineWE: - BUS_RegBitWrite(polRegister, _EBI_POLARITY_WEPOL_SHIFT, polarity); - break; - case ebiLineRE: - BUS_RegBitWrite(polRegister, _EBI_POLARITY_REPOL_SHIFT, polarity); - break; - case ebiLineCS: - BUS_RegBitWrite(polRegister, _EBI_POLARITY_CSPOL_SHIFT, polarity); - break; -#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) - case ebiLineBL: - BUS_RegBitWrite(polRegister, _EBI_POLARITY_BLPOL_SHIFT, polarity); - break; - case ebiLineTFTVSync: - BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_VSYNCPOL_SHIFT, polarity); - break; - case ebiLineTFTHSync: - BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_HSYNCPOL_SHIFT, polarity); - break; - case ebiLineTFTDataEn: - BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DATAENPOL_SHIFT, polarity); - break; - case ebiLineTFTDClk: - BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DCLKPOL_SHIFT, polarity); - break; - case ebiLineTFTCS: - BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_CSPOL_SHIFT, polarity); - break; -#endif - default: - EFM_ASSERT(0); - break; - } - banks = banks & ~bankSet; - } -} - - -/***************************************************************************//** - * @brief - * Configure Byte Lane Enable for select banks - * timing support - * - * @param[in] banks - * Mask of memory bank(s) to configure polarity for - * - * @param[in] enable - * Flag - ******************************************************************************/ -void EBI_BankByteLaneEnable(uint32_t banks, bool enable) -{ - /* Verify only valid banks are used */ - EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); - - /* Configure byte lane support for each selected bank */ - if (banks & EBI_BANK0) - { - BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL_SHIFT, enable); - } - if (banks & EBI_BANK1) - { - BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL1_SHIFT, enable); - } - if (banks & EBI_BANK2) - { - BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL2_SHIFT, enable); - } - if (banks & EBI_BANK3) - { - BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL3_SHIFT, enable); - } -} - - -/***************************************************************************//** - * @brief - * Configure Alternate Address Map support - * Enables or disables 256MB address range for all banks - * - * @param[in] enable - * Set or clear address map extension - ******************************************************************************/ -void EBI_AltMapEnable(bool enable) -{ - BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_ALTMAP_SHIFT, enable); -} - -#endif - -/** @} (end addtogroup EBI) */ -/** @} (end addtogroup EM_Library) */ - -#endif /* defined(EBI_COUNT) && (EBI_COUNT > 0) */ +/***************************************************************************//** + * @file em_ebi.c + * @brief External Bus Interface (EBI) Peripheral API + * @version 4.2.1 + ******************************************************************************* + * @section License + * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b> + ******************************************************************************* + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no + * obligation to support this Software. Silicon Labs is providing the + * Software "AS IS", with no express or implied warranties of any kind, + * including, but not limited to, any implied warranties of merchantability + * or fitness for any particular purpose or warranties against infringement + * of any proprietary rights of a third party. + * + * Silicon Labs will not be liable for any consequential, incidental, or + * special damages, or any other relief, or for any claim by any third party, + * arising from your use of this Software. + * + ******************************************************************************/ + +#include "em_ebi.h" +#if defined(EBI_COUNT) && (EBI_COUNT > 0) +#include "em_assert.h" +#include "em_bus.h" + +/***************************************************************************//** + * @addtogroup EM_Library + * @{ + ******************************************************************************/ + +/***************************************************************************//** + * @addtogroup EBI + * @brief EBI External Bus Interface (EBI) Peripheral API + * @{ + ******************************************************************************/ + +/***************************************************************************//** + * @brief + * Configure and enable External Bus Interface + * + * @param[in] ebiInit + * EBI configuration structure + * + * @note + * GPIO lines must be configured as PUSH_PULL for correct operation + * GPIO and EBI clocks must be enabled in the CMU + ******************************************************************************/ +void EBI_Init(const EBI_Init_TypeDef *ebiInit) +{ + uint32_t ctrl = EBI->CTRL; + +#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) + /* Enable Independent Timing for devices that supports it */ + ctrl |= EBI_CTRL_ITS; + + /* Set polarity of address ready */ + EBI_BankPolaritySet(ebiInit->banks, ebiLineARDY, ebiInit->ardyPolarity); + /* Set polarity of address latch enable */ + EBI_BankPolaritySet(ebiInit->banks, ebiLineALE, ebiInit->alePolarity); + /* Set polarity of write enable */ + EBI_BankPolaritySet(ebiInit->banks, ebiLineWE, ebiInit->wePolarity); + /* Set polarity of read enable */ + EBI_BankPolaritySet(ebiInit->banks, ebiLineRE, ebiInit->rePolarity); + /* Set polarity of chip select lines */ + EBI_BankPolaritySet(ebiInit->banks, ebiLineCS, ebiInit->csPolarity); + /* Set polarity of byte lane line */ + EBI_BankPolaritySet(ebiInit->banks, ebiLineBL, ebiInit->blPolarity); +#else + /* Set polarity of address ready */ + EBI_PolaritySet(ebiLineARDY, ebiInit->ardyPolarity); + /* Set polarity of address latch enable */ + EBI_PolaritySet(ebiLineALE, ebiInit->alePolarity); + /* Set polarity of write enable */ + EBI_PolaritySet(ebiLineWE, ebiInit->wePolarity); + /* Set polarity of read enable */ + EBI_PolaritySet(ebiLineRE, ebiInit->rePolarity); + /* Set polarity of chip select lines */ + EBI_PolaritySet(ebiLineCS, ebiInit->csPolarity); +#endif + + /* Configure EBI mode and control settings */ +#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) + if (ebiInit->banks & EBI_BANK0) + { + ctrl &= ~(_EBI_CTRL_MODE_MASK + | _EBI_CTRL_ARDYEN_MASK + | _EBI_CTRL_ARDYTODIS_MASK + | _EBI_CTRL_BL_MASK + | _EBI_CTRL_NOIDLE_MASK + | _EBI_CTRL_BANK0EN_MASK); + ctrl |= (ebiInit->mode << _EBI_CTRL_MODE_SHIFT); + ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDYEN_SHIFT); + ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTODIS_SHIFT); + ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL_SHIFT); + ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE_SHIFT); + if ( ebiInit->enable) + { + ctrl |= EBI_CTRL_BANK0EN; + } + } + if (ebiInit->banks & EBI_BANK1) + { + ctrl &= ~(_EBI_CTRL_BL1_MASK + | _EBI_CTRL_MODE1_MASK + | _EBI_CTRL_ARDY1EN_MASK + | _EBI_CTRL_ARDYTO1DIS_MASK + | _EBI_CTRL_NOIDLE1_MASK + | _EBI_CTRL_BANK1EN_MASK); + ctrl |= (ebiInit->mode << _EBI_CTRL_MODE1_SHIFT); + ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY1EN_SHIFT); + ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO1DIS_SHIFT); + ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL1_SHIFT); + ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE1_SHIFT); + if ( ebiInit->enable) + { + ctrl |= EBI_CTRL_BANK1EN; + } + } + if (ebiInit->banks & EBI_BANK2) + { + ctrl &= ~(_EBI_CTRL_BL2_MASK + | _EBI_CTRL_MODE2_MASK + | _EBI_CTRL_ARDY2EN_MASK + | _EBI_CTRL_ARDYTO2DIS_MASK + | _EBI_CTRL_NOIDLE2_MASK + | _EBI_CTRL_BANK2EN_MASK); + ctrl |= (ebiInit->mode << _EBI_CTRL_MODE2_SHIFT); + ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY2EN_SHIFT); + ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO2DIS_SHIFT); + ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL2_SHIFT); + ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE2_SHIFT); + if ( ebiInit->enable) + { + ctrl |= EBI_CTRL_BANK2EN; + } + } + if (ebiInit->banks & EBI_BANK3) + { + ctrl &= ~(_EBI_CTRL_BL3_MASK + | _EBI_CTRL_MODE3_MASK + | _EBI_CTRL_ARDY3EN_MASK + | _EBI_CTRL_ARDYTO3DIS_MASK + | _EBI_CTRL_NOIDLE3_MASK + | _EBI_CTRL_BANK3EN_MASK); + ctrl |= (ebiInit->mode << _EBI_CTRL_MODE3_SHIFT); + ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY3EN_SHIFT); + ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO3DIS_SHIFT); + ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL3_SHIFT); + ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE3_SHIFT); + if ( ebiInit->enable) + { + ctrl |= EBI_CTRL_BANK3EN; + } + } +#else + ctrl &= ~(_EBI_CTRL_MODE_MASK + | _EBI_CTRL_ARDYEN_MASK + | _EBI_CTRL_ARDYTODIS_MASK + | _EBI_CTRL_BANK0EN_MASK + | _EBI_CTRL_BANK1EN_MASK + | _EBI_CTRL_BANK2EN_MASK + | _EBI_CTRL_BANK3EN_MASK); + if ( ebiInit->enable) + { + if ( ebiInit->banks & EBI_BANK0 ) + { + ctrl |= EBI_CTRL_BANK0EN; + } + if ( ebiInit->banks & EBI_BANK1 ) + { + ctrl |= EBI_CTRL_BANK1EN; + } + if ( ebiInit->banks & EBI_BANK2 ) + { + ctrl |= EBI_CTRL_BANK2EN; + } + if ( ebiInit->banks & EBI_BANK3 ) + { + ctrl |= EBI_CTRL_BANK3EN; + } + } + ctrl |= ebiInit->mode; + ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDYEN_SHIFT); + ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTODIS_SHIFT); +#endif + + /* Configure timing */ +#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) + EBI_BankReadTimingSet(ebiInit->banks, + ebiInit->readSetupCycles, + ebiInit->readStrobeCycles, + ebiInit->readHoldCycles); + EBI_BankReadTimingConfig(ebiInit->banks, + ebiInit->readPageMode, + ebiInit->readPrefetch, + ebiInit->readHalfRE); + EBI_BankWriteTimingSet(ebiInit->banks, + ebiInit->writeSetupCycles, + ebiInit->writeStrobeCycles, + ebiInit->writeHoldCycles); + EBI_BankWriteTimingConfig(ebiInit->banks, + ebiInit->writeBufferDisable, + ebiInit->writeHalfWE); + EBI_BankAddressTimingSet(ebiInit->banks, + ebiInit->addrSetupCycles, + ebiInit->addrHoldCycles); + EBI_BankAddressTimingConfig(ebiInit->banks, + ebiInit->addrHalfALE); +#else + EBI_ReadTimingSet(ebiInit->readSetupCycles, + ebiInit->readStrobeCycles, + ebiInit->readHoldCycles); + EBI_WriteTimingSet(ebiInit->writeSetupCycles, + ebiInit->writeStrobeCycles, + ebiInit->writeHoldCycles); + EBI_AddressTimingSet(ebiInit->addrSetupCycles, + ebiInit->addrHoldCycles); +#endif + + /* Activate new configuration */ + EBI->CTRL = ctrl; + + /* Configure Adress Latch Enable */ + switch (ebiInit->mode) + { + case ebiModeD16A16ALE: + case ebiModeD8A24ALE: + /* Address Latch Enable */ + BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_ALEPEN_SHIFT, 1); + break; +#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) + case ebiModeD16: +#endif + case ebiModeD8A8: + /* Make sure Address Latch is disabled */ + BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_ALEPEN_SHIFT, 0); + break; + } +#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) + /* Limit pin enable */ + EBI->ROUTE = (EBI->ROUTE & ~_EBI_ROUTE_ALB_MASK) | ebiInit->aLow; + EBI->ROUTE = (EBI->ROUTE & ~_EBI_ROUTE_APEN_MASK) | ebiInit->aHigh; + /* Location */ + EBI->ROUTE = (EBI->ROUTE & ~_EBI_ROUTE_LOCATION_MASK) | ebiInit->location; + + /* Enable EBI BL pin if necessary */ + if(ctrl & (_EBI_CTRL_BL_MASK|_EBI_CTRL_BL1_MASK|_EBI_CTRL_BL2_MASK|_EBI_CTRL_BL3_MASK)) + { + BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_BLPEN_SHIFT, ebiInit->blEnable); + } +#endif + /* Enable EBI pins EBI_WEn and EBI_REn */ + BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_EBIPEN_SHIFT, 1); + + /* Enable chip select lines */ + EBI_ChipSelectEnable(ebiInit->csLines, true); +} + + +/***************************************************************************//** + * @brief + * Disable External Bus Interface + ******************************************************************************/ +void EBI_Disable(void) +{ + /* Disable pins */ + EBI->ROUTE = _EBI_ROUTE_RESETVALUE; + /* Disable banks */ + EBI->CTRL = _EBI_CTRL_RESETVALUE; +} + + +/***************************************************************************//** + * @brief + * Enable or disable EBI Bank + * + * @param[in] banks + * Banks to reconfigure, mask of EBI_BANK<n> flags + * + * @param[in] enable + * True to enable, false to disable + ******************************************************************************/ +void EBI_BankEnable(uint32_t banks, bool enable) +{ + if (banks & EBI_BANK0) + { + BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK0EN_SHIFT, enable); + } + if (banks & EBI_BANK1) + { + BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK1EN_SHIFT, enable); + } + if (banks & EBI_BANK2) + { + BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK2EN_SHIFT, enable); + } + if (banks & EBI_BANK3) + { + BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK3EN_SHIFT, enable); + } +} + + +/***************************************************************************//** + * @brief + * Return base address of EBI bank + * + * @param[in] bank + * Bank to return start address for + * + * @return + * Absolute address of bank + ******************************************************************************/ +uint32_t EBI_BankAddress(uint32_t bank) +{ +#if defined (_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) + if(EBI->CTRL & EBI_CTRL_ALTMAP) + { + switch (bank) + { + case EBI_BANK0: + return(EBI_MEM_BASE); + + case EBI_BANK1: + return(EBI_MEM_BASE + 0x10000000UL); + + case EBI_BANK2: + return(EBI_MEM_BASE + 0x20000000UL); + + case EBI_BANK3: + return(EBI_MEM_BASE + 0x30000000UL); + + default: + EFM_ASSERT(0); + break; + } + } +#endif + switch (bank) + { + case EBI_BANK0: + return(EBI_MEM_BASE); + + case EBI_BANK1: + return(EBI_MEM_BASE + 0x04000000UL); + + case EBI_BANK2: + return(EBI_MEM_BASE + 0x08000000UL); + + case EBI_BANK3: + return(EBI_MEM_BASE + 0x0C000000UL); + + default: + EFM_ASSERT(0); + break; + } + return 0; +} + + +/***************************************************************************//** + * @brief + * Enable or disable EBI Chip Select + * + * @param[in] cs + * ChipSelect lines to reconfigure, mask of EBI_CS<n> flags + * + * @param[in] enable + * True to enable, false to disable + ******************************************************************************/ +void EBI_ChipSelectEnable(uint32_t cs, bool enable) +{ + if (cs & EBI_CS0) + { + BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_CS0PEN_SHIFT, enable); + } + if (cs & EBI_CS1) + { + BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_CS1PEN_SHIFT, enable); + } + if (cs & EBI_CS2) + { + BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_CS2PEN_SHIFT, enable); + } + if (cs & EBI_CS3) + { + BUS_RegBitWrite(&(EBI->ROUTE), _EBI_ROUTE_CS3PEN_SHIFT, enable); + } +} + + +/***************************************************************************//** + * @brief + * Configure EBI pin polarity + * + * @param[in] line + * Which pin/line to configure + * + * @param[in] polarity + * Active high, or active low + ******************************************************************************/ +void EBI_PolaritySet(EBI_Line_TypeDef line, EBI_Polarity_TypeDef polarity) +{ + switch (line) + { + case ebiLineARDY: + BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_ARDYPOL_SHIFT, polarity); + break; + case ebiLineALE: + BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_ALEPOL_SHIFT, polarity); + break; + case ebiLineWE: + BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_WEPOL_SHIFT, polarity); + break; + case ebiLineRE: + BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_REPOL_SHIFT, polarity); + break; + case ebiLineCS: + BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_CSPOL_SHIFT, polarity); + break; +#if defined (_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) + case ebiLineBL: + BUS_RegBitWrite(&(EBI->POLARITY), _EBI_POLARITY_BLPOL_SHIFT, polarity); + break; + case ebiLineTFTVSync: + BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_VSYNCPOL_SHIFT, polarity); + break; + case ebiLineTFTHSync: + BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_HSYNCPOL_SHIFT, polarity); + break; + case ebiLineTFTDataEn: + BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DATAENPOL_SHIFT, polarity); + break; + case ebiLineTFTDClk: + BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DCLKPOL_SHIFT, polarity); + break; + case ebiLineTFTCS: + BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_CSPOL_SHIFT, polarity); + break; +#endif + default: + EFM_ASSERT(0); + break; + } +} + + +/***************************************************************************//** + * @brief + * Configure timing values of read bus accesses + * + * @param[in] setupCycles + * Number of clock cycles for address setup before REn is asserted + * + * @param[in] strobeCycles + * The number of cycles the REn is held active. After the specified number of + * cycles, data is read. If set to 0, 1 cycle is inserted by HW + * + * @param[in] holdCycles + * The number of cycles CSn is held active after the REn is dessarted + ******************************************************************************/ +void EBI_ReadTimingSet(int setupCycles, int strobeCycles, int holdCycles) +{ + uint32_t readTiming; + + /* Check that timings are within limits */ + EFM_ASSERT(setupCycles < 4); + EFM_ASSERT(strobeCycles < 16); + EFM_ASSERT(holdCycles < 4); + + /* Configure timing values */ + readTiming = (setupCycles << _EBI_RDTIMING_RDSETUP_SHIFT) + | (strobeCycles << _EBI_RDTIMING_RDSTRB_SHIFT) + | (holdCycles << _EBI_RDTIMING_RDHOLD_SHIFT); + + + EBI->RDTIMING = (EBI->RDTIMING + & ~(_EBI_RDTIMING_RDSETUP_MASK + | _EBI_RDTIMING_RDSTRB_MASK + | _EBI_RDTIMING_RDHOLD_MASK)) + | readTiming; +} + + +/***************************************************************************//** + * @brief + * Configure timing values of write bus accesses + * + * @param[in] setupCycles + * Number of clock cycles for address setup before WEn is asserted + * + * @param[in] strobeCycles + * Number of cycles WEn is held active. If set to 0, 1 cycle is inserted by HW + * + * @param[in] holdCycles + * Number of cycles CSn is held active after the WEn is deasserted + ******************************************************************************/ +void EBI_WriteTimingSet(int setupCycles, int strobeCycles, int holdCycles) +{ + uint32_t writeTiming; + + /* Check that timings are within limits */ + EFM_ASSERT(setupCycles < 4); + EFM_ASSERT(strobeCycles < 16); + EFM_ASSERT(holdCycles < 4); + + /* Configure timing values */ + writeTiming = (setupCycles << _EBI_WRTIMING_WRSETUP_SHIFT) + | (strobeCycles << _EBI_WRTIMING_WRSTRB_SHIFT) + | (holdCycles << _EBI_WRTIMING_WRHOLD_SHIFT); + + EBI->WRTIMING = (EBI->WRTIMING + & ~(_EBI_WRTIMING_WRSETUP_MASK + | _EBI_WRTIMING_WRSTRB_MASK + | _EBI_WRTIMING_WRHOLD_MASK)) + | writeTiming; +} + + +/***************************************************************************//** + * @brief + * Configure timing values of address latch bus accesses + * + * @param[in] setupCycles + * Sets the number of cycles the address is held after ALE is asserted + * + * @param[in] holdCycles + * Sets the number of cycles the address is driven onto the ADDRDAT bus before + * ALE is asserted. If set 0, 1 cycle is inserted by HW + ******************************************************************************/ +void EBI_AddressTimingSet(int setupCycles, int holdCycles) +{ + uint32_t addressLatchTiming; + + /* Check that timing values are within limits */ + EFM_ASSERT(setupCycles < 4); + EFM_ASSERT(holdCycles < 4); + + /* Configure address latch timing values */ + addressLatchTiming = (setupCycles << _EBI_ADDRTIMING_ADDRSETUP_SHIFT) + | (holdCycles << _EBI_ADDRTIMING_ADDRHOLD_SHIFT); + + EBI->ADDRTIMING = (EBI->ADDRTIMING + & ~(_EBI_ADDRTIMING_ADDRSETUP_MASK + | _EBI_ADDRTIMING_ADDRHOLD_MASK)) + | addressLatchTiming; +} + +#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) +/***************************************************************************//** + * @brief + * Configure and initialize TFT Direct Drive + * + * @param[in] ebiTFTInit + * TFT Initialization structure + ******************************************************************************/ +void EBI_TFTInit(const EBI_TFTInit_TypeDef *ebiTFTInit) +{ + uint32_t ctrl; + + /* Configure base address for frame buffer offset to EBI bank */ + EBI_TFTFrameBaseSet(ebiTFTInit->addressOffset); + + /* Configure display size and porch areas */ + EBI_TFTSizeSet(ebiTFTInit->hsize, + ebiTFTInit->vsize); + EBI_TFTHPorchSet(ebiTFTInit->hPorchFront, + ebiTFTInit->hPorchBack, + ebiTFTInit->hPulseWidth); + EBI_TFTVPorchSet(ebiTFTInit->vPorchFront, + ebiTFTInit->vPorchBack, + ebiTFTInit->vPulseWidth); + + /* Configure timing settings */ + EBI_TFTTimingSet(ebiTFTInit->dclkPeriod, + ebiTFTInit->startPosition, + ebiTFTInit->setupCycles, + ebiTFTInit->holdCycles); + + /* Configure line polarity settings */ + EBI_PolaritySet(ebiLineTFTCS, ebiTFTInit->csPolarity); + EBI_PolaritySet(ebiLineTFTDClk, ebiTFTInit->dclkPolarity); + EBI_PolaritySet(ebiLineTFTDataEn, ebiTFTInit->dataenPolarity); + EBI_PolaritySet(ebiLineTFTVSync, ebiTFTInit->vsyncPolarity); + EBI_PolaritySet(ebiLineTFTHSync, ebiTFTInit->hsyncPolarity); + + /* Main control, EBI bank select, mask and blending configuration */ + ctrl = (uint32_t)ebiTFTInit->bank + | (uint32_t)ebiTFTInit->width + | (uint32_t)ebiTFTInit->colSrc + | (uint32_t)ebiTFTInit->interleave + | (uint32_t)ebiTFTInit->fbTrigger + | (uint32_t)(ebiTFTInit->shiftDClk == true + ? (1 << _EBI_TFTCTRL_SHIFTDCLKEN_SHIFT) : 0) + | (uint32_t)ebiTFTInit->maskBlend + | (uint32_t)ebiTFTInit->driveMode; + + EBI->TFTCTRL = ctrl; + + /* Enable TFT pins */ + if (ebiTFTInit->driveMode != ebiTFTDDModeDisabled) + { + EBI->ROUTE |= EBI_ROUTE_TFTPEN; + } +} + + +/***************************************************************************//** + * @brief + * Configure and initialize TFT size settings + * + * @param[in] horizontal + * TFT display horizontal size in pixels + * @param[in] vertical + * TFT display vertical size in pixels + ******************************************************************************/ +void EBI_TFTSizeSet(uint32_t horizontal, uint32_t vertical) +{ + EFM_ASSERT((horizontal-1) < 1024); + EFM_ASSERT((vertical-1) < 1024); + + EBI->TFTSIZE = ((horizontal-1) << _EBI_TFTSIZE_HSZ_SHIFT) + | ((vertical-1) << _EBI_TFTSIZE_VSZ_SHIFT); +} + +/***************************************************************************//** + * @brief + * Configure and initialize Horizontal Porch Settings + * + * @param[in] front + * Horizontal front porch size in pixels + * @param[in] back + * Horizontal back porch size in pixels + * @param[in] pulseWidth + * Horizontal synchronization pulse width. Set to required -1. + ******************************************************************************/ +void EBI_TFTHPorchSet(int front, int back, int pulseWidth) +{ + EFM_ASSERT(front < 256); + EFM_ASSERT(back < 256); + EFM_ASSERT((pulseWidth-1) < 128); + + EBI->TFTHPORCH = (front << _EBI_TFTHPORCH_HFPORCH_SHIFT) + | (back << _EBI_TFTHPORCH_HBPORCH_SHIFT) + | ((pulseWidth-1) << _EBI_TFTHPORCH_HSYNC_SHIFT); +} + + +/***************************************************************************//** + * @brief + * Configure Vertical Porch Settings + * + * @param[in] front + * Vertical front porch size in pixels + * @param[in] back + * Vertical back porch size in pixels + * @param[in] pulseWidth + * Vertical synchronization pulse width. Set to required -1. + ******************************************************************************/ +void EBI_TFTVPorchSet(int front, int back, int pulseWidth) +{ + EFM_ASSERT(front < 256); + EFM_ASSERT(back < 256); + EFM_ASSERT((pulseWidth-1) < 128); + + EBI->TFTVPORCH = (front << _EBI_TFTVPORCH_VFPORCH_SHIFT) + | (back << _EBI_TFTVPORCH_VBPORCH_SHIFT) + | ((pulseWidth-1) << _EBI_TFTVPORCH_VSYNC_SHIFT); +} + + +/***************************************************************************//** + * @brief + * Configure TFT Direct Drive Timing Settings + * + * @param[in] dclkPeriod + * DCLK period in internal cycles + * + * @param[in] start + * Starting position of external direct drive, relative to DCLK inactive edge + * + * @param[in] setup + * Number of cycles RGB data is driven before active edge of DCLK + * + * @param[in] hold + * Number of cycles RGB data is held after active edge of DCLK + ******************************************************************************/ +void EBI_TFTTimingSet(int dclkPeriod, int start, int setup, int hold) +{ + EFM_ASSERT(dclkPeriod < 2048); + EFM_ASSERT(start < 2048); + EFM_ASSERT(setup < 4); + EFM_ASSERT(hold < 4); + + EBI->TFTTIMING = (dclkPeriod << _EBI_TFTTIMING_DCLKPERIOD_SHIFT) + | (start << _EBI_TFTTIMING_TFTSTART_SHIFT) + | (setup << _EBI_TFTTIMING_TFTSETUP_SHIFT) + | (hold << _EBI_TFTTIMING_TFTHOLD_SHIFT); +} +#endif + +#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) +/***************************************************************************//** + * @brief + * Configure read operation parameters for selected bank + * + * @param[in] banks + * Mask of memory bank(s) to configure write timing for + * + * @param[in] pageMode + * Enables or disables half cycle WE strobe in last strobe cycle + * + * @param[in] prefetch + * Enables or disables half cycle WE strobe in last strobe cycle + * + * @param[in] halfRE + * Enables or disables half cycle WE strobe in last strobe cycle + ******************************************************************************/ +void EBI_BankReadTimingConfig(uint32_t banks, bool pageMode, bool prefetch, bool halfRE) +{ + /* Verify only valid banks are used */ + EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); + + /* Configure read operation parameters */ + if( banks & EBI_BANK0 ) + { + BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); + BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); + BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_HALFRE_SHIFT, halfRE); + } + if( banks & EBI_BANK1 ) + { + BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); + BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); + BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_HALFRE_SHIFT, halfRE); + } + if( banks & EBI_BANK2 ) + { + BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); + BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); + BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_HALFRE_SHIFT, halfRE); + } + if( banks & EBI_BANK3 ) + { + BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); + BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); + BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_HALFRE_SHIFT, halfRE); + } +} + +/***************************************************************************//** + * @brief + * Configure timing values of read bus accesses + * + * @param[in] banks + * Mask of memory bank(s) to configure timing for + * + * @param[in] setupCycles + * Number of clock cycles for address setup before REn is asserted + * + * @param[in] strobeCycles + * The number of cycles the REn is held active. After the specified number of + * cycles, data is read. If set to 0, 1 cycle is inserted by HW + * + * @param[in] holdCycles + * The number of cycles CSn is held active after the REn is dessarted + ******************************************************************************/ +void EBI_BankReadTimingSet(uint32_t banks, int setupCycles, int strobeCycles, int holdCycles) +{ + uint32_t readTiming; + + /* Verify only valid banks are used */ + EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); + + /* Check that timings are within limits */ + EFM_ASSERT(setupCycles < 4); + EFM_ASSERT(strobeCycles < 64); + EFM_ASSERT(holdCycles < 4); + + /* Configure timing values */ + readTiming = (setupCycles << _EBI_RDTIMING_RDSETUP_SHIFT) + | (strobeCycles << _EBI_RDTIMING_RDSTRB_SHIFT) + | (holdCycles << _EBI_RDTIMING_RDHOLD_SHIFT); + + if (banks & EBI_BANK0) + { + EBI->RDTIMING = (EBI->RDTIMING + & ~(_EBI_RDTIMING_RDSETUP_MASK + | _EBI_RDTIMING_RDSTRB_MASK + | _EBI_RDTIMING_RDHOLD_MASK)) + | readTiming; + } + if (banks & EBI_BANK1) + { + EBI->RDTIMING1 = (EBI->RDTIMING1 + & ~(_EBI_RDTIMING1_RDSETUP_MASK + | _EBI_RDTIMING1_RDSTRB_MASK + | _EBI_RDTIMING1_RDHOLD_MASK)) + | readTiming; + } + if (banks & EBI_BANK2) + { + EBI->RDTIMING2 = (EBI->RDTIMING2 + & ~(_EBI_RDTIMING2_RDSETUP_MASK + | _EBI_RDTIMING2_RDSTRB_MASK + | _EBI_RDTIMING2_RDHOLD_MASK)) + | readTiming; + } + if (banks & EBI_BANK3) + { + EBI->RDTIMING3 = (EBI->RDTIMING3 + & ~(_EBI_RDTIMING3_RDSETUP_MASK + | _EBI_RDTIMING3_RDSTRB_MASK + | _EBI_RDTIMING3_RDHOLD_MASK)) + | readTiming; + } +} + + +/***************************************************************************//** + * @brief + * Configure write operation parameters for selected bank + * + * @param[in] banks + * Mask of memory bank(s) to configure write timing for + * + * @param[in] writeBufDisable + * If true, disable the write buffer + * + * @param[in] halfWE + * Enables or disables half cycle WE strobe in last strobe cycle + ******************************************************************************/ +void EBI_BankWriteTimingConfig(uint32_t banks, bool writeBufDisable, bool halfWE) +{ + /* Verify only valid banks are used */ + EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); + + /* Configure write operation parameters */ + if( banks & EBI_BANK0 ) + { + BUS_RegBitWrite(&EBI->WRTIMING, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); + BUS_RegBitWrite(&EBI->WRTIMING, _EBI_WRTIMING_HALFWE_SHIFT, halfWE); + } + if( banks & EBI_BANK1 ) + { + BUS_RegBitWrite(&EBI->WRTIMING1, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); + BUS_RegBitWrite(&EBI->WRTIMING1, _EBI_WRTIMING_HALFWE_SHIFT, halfWE); + } + if( banks & EBI_BANK2 ) + { + BUS_RegBitWrite(&EBI->WRTIMING2, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); + BUS_RegBitWrite(&EBI->WRTIMING2, _EBI_WRTIMING_HALFWE_SHIFT, halfWE); + } + if( banks & EBI_BANK3 ) + { + BUS_RegBitWrite(&EBI->WRTIMING3, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); + BUS_RegBitWrite(&EBI->WRTIMING3, _EBI_WRTIMING_HALFWE_SHIFT, halfWE); + } +} + + +/***************************************************************************//** + * @brief + * Configure timing values of write bus accesses + * + * @param[in] banks + * Mask of memory bank(s) to configure write timing for + * + * @param[in] setupCycles + * Number of clock cycles for address setup before WEn is asserted + * + * @param[in] strobeCycles + * Number of cycles WEn is held active. If set to 0, 1 cycle is inserted by HW + * + * @param[in] holdCycles + * Number of cycles CSn is held active after the WEn is deasserted + ******************************************************************************/ +void EBI_BankWriteTimingSet(uint32_t banks, int setupCycles, int strobeCycles, int holdCycles) +{ + uint32_t writeTiming; + + /* Verify only valid banks are used */ + EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); + + /* Check that timings are within limits */ + EFM_ASSERT(setupCycles < 4); + EFM_ASSERT(strobeCycles < 64); + EFM_ASSERT(holdCycles < 4); + + /* Configure timing values */ + writeTiming = (setupCycles << _EBI_WRTIMING_WRSETUP_SHIFT) + | (strobeCycles << _EBI_WRTIMING_WRSTRB_SHIFT) + | (holdCycles << _EBI_WRTIMING_WRHOLD_SHIFT); + + if (banks & EBI_BANK0) + { + EBI->WRTIMING = (EBI->WRTIMING + & ~(_EBI_WRTIMING_WRSETUP_MASK + | _EBI_WRTIMING_WRSTRB_MASK + | _EBI_WRTIMING_WRHOLD_MASK)) + | writeTiming; + } + if (banks & EBI_BANK1) + { + EBI->WRTIMING1 = (EBI->WRTIMING1 + & ~(_EBI_WRTIMING1_WRSETUP_MASK + | _EBI_WRTIMING1_WRSTRB_MASK + | _EBI_WRTIMING1_WRHOLD_MASK)) + | writeTiming; + } + if (banks & EBI_BANK2) + { + EBI->WRTIMING2 = (EBI->WRTIMING2 + & ~(_EBI_WRTIMING2_WRSETUP_MASK + | _EBI_WRTIMING2_WRSTRB_MASK + | _EBI_WRTIMING2_WRHOLD_MASK)) + | writeTiming; + } + if (banks & EBI_BANK3) + { + EBI->WRTIMING3 = (EBI->WRTIMING3 + & ~(_EBI_WRTIMING3_WRSETUP_MASK + | _EBI_WRTIMING3_WRSTRB_MASK + | _EBI_WRTIMING3_WRHOLD_MASK)) + | writeTiming; + } +} + + +/***************************************************************************//** + * @brief + * Configure address operation parameters for selected bank + * + * @param[in] banks + * Mask of memory bank(s) to configure write timing for + * + * @param[in] halfALE + * Enables or disables half cycle ALE strobe in last strobe cycle + ******************************************************************************/ +void EBI_BankAddressTimingConfig(uint32_t banks, bool halfALE) +{ + /* Verify only valid banks are used */ + EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); + + if( banks & EBI_BANK0 ) + { + BUS_RegBitWrite(&EBI->ADDRTIMING, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE); + } + if( banks & EBI_BANK1 ) + { + BUS_RegBitWrite(&EBI->ADDRTIMING1, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE); + } + if( banks & EBI_BANK2 ) + { + BUS_RegBitWrite(&EBI->ADDRTIMING2, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE); + } + if( banks & EBI_BANK3 ) + { + BUS_RegBitWrite(&EBI->ADDRTIMING3, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE); + } +} + + +/***************************************************************************//** + * @brief + * Configure timing values of address latch bus accesses + * + * @param[in] banks + * Mask of memory bank(s) to configure address timing for + * + * @param[in] setupCycles + * Sets the number of cycles the address is held after ALE is asserted + * + * @param[in] holdCycles + * Sets the number of cycles the address is driven onto the ADDRDAT bus before + * ALE is asserted. If set 0, 1 cycle is inserted by HW + ******************************************************************************/ +void EBI_BankAddressTimingSet(uint32_t banks, int setupCycles, int holdCycles) +{ + uint32_t addressLatchTiming; + + /* Verify only valid banks are used */ + EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); + + /* Check that timing values are within limits */ + EFM_ASSERT(setupCycles < 4); + EFM_ASSERT(holdCycles < 4); + + /* Configure address latch timing values */ + addressLatchTiming = (setupCycles << _EBI_ADDRTIMING_ADDRSETUP_SHIFT) + | (holdCycles << _EBI_ADDRTIMING_ADDRHOLD_SHIFT); + + if (banks & EBI_BANK0) + { + EBI->ADDRTIMING = (EBI->ADDRTIMING + & ~(_EBI_ADDRTIMING_ADDRSETUP_MASK + | _EBI_ADDRTIMING_ADDRHOLD_MASK)) + | addressLatchTiming; + } + if (banks & EBI_BANK1) + { + EBI->ADDRTIMING1 = (EBI->ADDRTIMING1 + & ~(_EBI_ADDRTIMING1_ADDRSETUP_MASK + | _EBI_ADDRTIMING1_ADDRHOLD_MASK)) + | addressLatchTiming; + } + if (banks & EBI_BANK2) + { + EBI->ADDRTIMING2 = (EBI->ADDRTIMING2 + & ~(_EBI_ADDRTIMING2_ADDRSETUP_MASK + | _EBI_ADDRTIMING2_ADDRHOLD_MASK)) + | addressLatchTiming; + } + if (banks & EBI_BANK3) + { + EBI->ADDRTIMING3 = (EBI->ADDRTIMING3 + & ~(_EBI_ADDRTIMING3_ADDRSETUP_MASK + | _EBI_ADDRTIMING3_ADDRHOLD_MASK)) + | addressLatchTiming; + } +} + + +/***************************************************************************//** + * @brief + * Configure EBI pin polarity for selected bank(s) for devices with individual + * timing support + * + * @param[in] banks + * Mask of memory bank(s) to configure polarity for + * + * @param[in] line + * Which pin/line to configure + * + * @param[in] polarity + * Active high, or active low + ******************************************************************************/ +void EBI_BankPolaritySet(uint32_t banks, EBI_Line_TypeDef line, EBI_Polarity_TypeDef polarity) +{ + uint32_t bankSet = 0; + volatile uint32_t *polRegister = 0; + + /* Verify only valid banks are used */ + EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); + + while (banks) + { +#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) + if (banks & EBI_BANK0) + { + polRegister = &EBI->POLARITY; + bankSet = EBI_BANK0; + } + if (banks & EBI_BANK1) + { + polRegister = &EBI->POLARITY1; + bankSet = EBI_BANK1; + } + if (banks & EBI_BANK2) + { + polRegister = &EBI->POLARITY2; + bankSet = EBI_BANK2; + } + if (banks & EBI_BANK3) + { + polRegister = &EBI->POLARITY3; + bankSet = EBI_BANK3; + } +#else + polRegister = &EBI->POLARITY; + banks = 0; +#endif + + /* What line to configure */ + switch (line) + { + case ebiLineARDY: + BUS_RegBitWrite(polRegister, _EBI_POLARITY_ARDYPOL_SHIFT, polarity); + break; + case ebiLineALE: + BUS_RegBitWrite(polRegister, _EBI_POLARITY_ALEPOL_SHIFT, polarity); + break; + case ebiLineWE: + BUS_RegBitWrite(polRegister, _EBI_POLARITY_WEPOL_SHIFT, polarity); + break; + case ebiLineRE: + BUS_RegBitWrite(polRegister, _EBI_POLARITY_REPOL_SHIFT, polarity); + break; + case ebiLineCS: + BUS_RegBitWrite(polRegister, _EBI_POLARITY_CSPOL_SHIFT, polarity); + break; +#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) + case ebiLineBL: + BUS_RegBitWrite(polRegister, _EBI_POLARITY_BLPOL_SHIFT, polarity); + break; + case ebiLineTFTVSync: + BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_VSYNCPOL_SHIFT, polarity); + break; + case ebiLineTFTHSync: + BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_HSYNCPOL_SHIFT, polarity); + break; + case ebiLineTFTDataEn: + BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DATAENPOL_SHIFT, polarity); + break; + case ebiLineTFTDClk: + BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DCLKPOL_SHIFT, polarity); + break; + case ebiLineTFTCS: + BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_CSPOL_SHIFT, polarity); + break; +#endif + default: + EFM_ASSERT(0); + break; + } + banks = banks & ~bankSet; + } +} + + +/***************************************************************************//** + * @brief + * Configure Byte Lane Enable for select banks + * timing support + * + * @param[in] banks + * Mask of memory bank(s) to configure polarity for + * + * @param[in] enable + * Flag + ******************************************************************************/ +void EBI_BankByteLaneEnable(uint32_t banks, bool enable) +{ + /* Verify only valid banks are used */ + EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0); + + /* Configure byte lane support for each selected bank */ + if (banks & EBI_BANK0) + { + BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL_SHIFT, enable); + } + if (banks & EBI_BANK1) + { + BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL1_SHIFT, enable); + } + if (banks & EBI_BANK2) + { + BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL2_SHIFT, enable); + } + if (banks & EBI_BANK3) + { + BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL3_SHIFT, enable); + } +} + + +/***************************************************************************//** + * @brief + * Configure Alternate Address Map support + * Enables or disables 256MB address range for all banks + * + * @param[in] enable + * Set or clear address map extension + ******************************************************************************/ +void EBI_AltMapEnable(bool enable) +{ + BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_ALTMAP_SHIFT, enable); +} + +#endif + +/** @} (end addtogroup EBI) */ +/** @} (end addtogroup EM_Library) */ + +#endif /* defined(EBI_COUNT) && (EBI_COUNT > 0) */