/***************************************************************************//** * @file * @brief External Bus Interface (EBI) Peripheral API for EFM32 * @author Energy Micro AS * @version 2.3.2 ******************************************************************************* * @section License * (C) Copyright 2010 Energy Micro AS, http://www.energymicro.com ******************************************************************************* * * This source code is the property of Energy Micro AS. The source and compiled * code may only be used on Energy Micro "EFM32" microcontrollers. * * This copyright notice may not be removed from the source code nor changed. * * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no * obligation to support this Software. Energy Micro AS 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. * * Energy Micro AS 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 "efm32_ebi.h" #if defined(EBI_COUNT) && (EBI_COUNT > 0) #include "efm32_assert.h" #include "efm32_bitband.h" #include /***************************************************************************//** * @addtogroup EFM32_Library * @{ ******************************************************************************/ /***************************************************************************//** * @addtogroup EBI * @brief EBI External Bus Interface (EBI) Peripheral API for EFM32 * @{ ******************************************************************************/ /***************************************************************************//** * @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) /* 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) 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) 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 /* Configure Adress Latch Enable */ switch (ebiInit->mode) { case ebiModeD16A16ALE: case ebiModeD8A24ALE: /* Address Latch Enable */ BITBAND_Peripheral(&(EBI->ROUTE), _EBI_ROUTE_ALEPEN_SHIFT, 1); break; #if defined(_EFM32_GIANT_FAMILY) case ebiModeD16: #endif case ebiModeD8A8: /* Make sure Address Latch is disabled */ BITBAND_Peripheral(&(EBI->ROUTE), _EBI_ROUTE_ALEPEN_SHIFT, 0); break; } #if defined(_EFM32_GIANT_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 pins BL, ADxx, WEn, REn */ BITBAND_Peripheral(&(EBI->ROUTE), _EBI_ROUTE_BLPEN_SHIFT, ebiInit->blEnable); #endif /* Enable EBI pins EBI_WEn and EBI_REn */ BITBAND_Peripheral(&(EBI->ROUTE), _EBI_ROUTE_EBIPEN_SHIFT, 1); /* Enable chip select lines */ EBI_ChipSelectEnable(ebiInit->csLines, true); /* Activate new configuration */ EBI->CTRL = ctrl; } /***************************************************************************//** * @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 flags * * @param[in] enable * True to enable, false to disable ******************************************************************************/ void EBI_BankEnable(uint32_t banks, bool enable) { if (banks & EBI_BANK0) { BITBAND_Peripheral(&(EBI->CTRL), _EBI_CTRL_BANK0EN_SHIFT, enable); } if (banks & EBI_BANK1) { BITBAND_Peripheral(&(EBI->CTRL), _EBI_CTRL_BANK1EN_SHIFT, enable); } if (banks & EBI_BANK2) { BITBAND_Peripheral(&(EBI->CTRL), _EBI_CTRL_BANK2EN_SHIFT, enable); } if (banks & EBI_BANK3) { BITBAND_Peripheral(&(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) 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 flags * * @param[in] enable * True to enable, false to disable ******************************************************************************/ void EBI_ChipSelectEnable(uint32_t cs, bool enable) { if (cs & EBI_CS0) { BITBAND_Peripheral(&(EBI->ROUTE), _EBI_ROUTE_CS0PEN_SHIFT, enable); } if (cs & EBI_CS1) { BITBAND_Peripheral(&(EBI->ROUTE), _EBI_ROUTE_CS1PEN_SHIFT, enable); } if (cs & EBI_CS2) { BITBAND_Peripheral(&(EBI->ROUTE), _EBI_ROUTE_CS2PEN_SHIFT, enable); } if (cs & EBI_CS3) { BITBAND_Peripheral(&(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: BITBAND_Peripheral(&(EBI->POLARITY), _EBI_POLARITY_ARDYPOL_SHIFT, polarity); break; case ebiLineALE: BITBAND_Peripheral(&(EBI->POLARITY), _EBI_POLARITY_ALEPOL_SHIFT, polarity); break; case ebiLineWE: BITBAND_Peripheral(&(EBI->POLARITY), _EBI_POLARITY_WEPOL_SHIFT, polarity); break; case ebiLineRE: BITBAND_Peripheral(&(EBI->POLARITY), _EBI_POLARITY_REPOL_SHIFT, polarity); break; case ebiLineCS: BITBAND_Peripheral(&(EBI->POLARITY), _EBI_POLARITY_CSPOL_SHIFT, polarity); break; #if defined (_EFM32_GIANT_FAMILY) case ebiLineBL: BITBAND_Peripheral(&(EBI->POLARITY), _EBI_POLARITY_BLPOL_SHIFT, polarity); break; case ebiLineTFTVSync: BITBAND_Peripheral(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_VSYNCPOL_SHIFT, polarity); break; case ebiLineTFTHSync: BITBAND_Peripheral(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_HSYNCPOL_SHIFT, polarity); break; case ebiLineTFTDataEn: BITBAND_Peripheral(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DATAENPOL_SHIFT, polarity); break; case ebiLineTFTDClk: BITBAND_Peripheral(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DCLKPOL_SHIFT, polarity); break; case ebiLineTFTCS: BITBAND_Peripheral(&(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) /***************************************************************************//** * @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) /***************************************************************************//** * @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 ) { BITBAND_Peripheral(&EBI->RDTIMING, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); BITBAND_Peripheral(&EBI->RDTIMING, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); BITBAND_Peripheral(&EBI->RDTIMING, _EBI_RDTIMING_HALFRE_SHIFT, halfRE); } if( banks & EBI_BANK1 ) { BITBAND_Peripheral(&EBI->RDTIMING1, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); BITBAND_Peripheral(&EBI->RDTIMING1, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); BITBAND_Peripheral(&EBI->RDTIMING1, _EBI_RDTIMING_HALFRE_SHIFT, halfRE); } if( banks & EBI_BANK2 ) { BITBAND_Peripheral(&EBI->RDTIMING2, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); BITBAND_Peripheral(&EBI->RDTIMING2, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); BITBAND_Peripheral(&EBI->RDTIMING2, _EBI_RDTIMING_HALFRE_SHIFT, halfRE); } if( banks & EBI_BANK3 ) { BITBAND_Peripheral(&EBI->RDTIMING3, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode); BITBAND_Peripheral(&EBI->RDTIMING3, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch); BITBAND_Peripheral(&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] writeBufferDisable * 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 ) { BITBAND_Peripheral(&EBI->WRTIMING, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); BITBAND_Peripheral(&EBI->WRTIMING, _EBI_WRTIMING_HALFWE_SHIFT, halfWE); } if( banks & EBI_BANK1 ) { BITBAND_Peripheral(&EBI->WRTIMING1, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); BITBAND_Peripheral(&EBI->WRTIMING1, _EBI_WRTIMING_HALFWE_SHIFT, halfWE); } if( banks & EBI_BANK2 ) { BITBAND_Peripheral(&EBI->WRTIMING2, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); BITBAND_Peripheral(&EBI->WRTIMING2, _EBI_WRTIMING_HALFWE_SHIFT, halfWE); } if( banks & EBI_BANK3 ) { BITBAND_Peripheral(&EBI->WRTIMING3, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable); BITBAND_Peripheral(&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 ) { BITBAND_Peripheral(&EBI->ADDRTIMING, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE); } if( banks & EBI_BANK1 ) { BITBAND_Peripheral(&EBI->ADDRTIMING1, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE); } if( banks & EBI_BANK2 ) { BITBAND_Peripheral(&EBI->ADDRTIMING2, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE); } if( banks & EBI_BANK3 ) { BITBAND_Peripheral(&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 = NULL; /* 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) 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: BITBAND_Peripheral(polRegister, _EBI_POLARITY_ARDYPOL_SHIFT, polarity); break; case ebiLineALE: BITBAND_Peripheral(polRegister, _EBI_POLARITY_ALEPOL_SHIFT, polarity); break; case ebiLineWE: BITBAND_Peripheral(polRegister, _EBI_POLARITY_WEPOL_SHIFT, polarity); break; case ebiLineRE: BITBAND_Peripheral(polRegister, _EBI_POLARITY_REPOL_SHIFT, polarity); break; case ebiLineCS: BITBAND_Peripheral(polRegister, _EBI_POLARITY_CSPOL_SHIFT, polarity); break; #if defined(_EFM32_GIANT_FAMILY) case ebiLineBL: BITBAND_Peripheral(polRegister, _EBI_POLARITY_BLPOL_SHIFT, polarity); break; case ebiLineTFTVSync: BITBAND_Peripheral(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_VSYNCPOL_SHIFT, polarity); break; case ebiLineTFTHSync: BITBAND_Peripheral(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_HSYNCPOL_SHIFT, polarity); break; case ebiLineTFTDataEn: BITBAND_Peripheral(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DATAENPOL_SHIFT, polarity); break; case ebiLineTFTDClk: BITBAND_Peripheral(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DCLKPOL_SHIFT, polarity); break; case ebiLineTFTCS: BITBAND_Peripheral(&(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) { BITBAND_Peripheral(&(EBI->CTRL), _EBI_CTRL_BL_SHIFT, enable); } if (banks & EBI_BANK1) { BITBAND_Peripheral(&(EBI->CTRL), _EBI_CTRL_BL1_SHIFT, enable); } if (banks & EBI_BANK2) { BITBAND_Peripheral(&(EBI->CTRL), _EBI_CTRL_BL2_SHIFT, enable); } if (banks & EBI_BANK3) { BITBAND_Peripheral(&(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) { BITBAND_Peripheral(&(EBI->CTRL), _EBI_CTRL_ALTMAP_SHIFT, enable); } #endif /** @} (end addtogroup EBI) */ /** @} (end addtogroup EFM32_Library) */ #endif /* defined(EBI_COUNT) && (EBI_COUNT > 0) */