/**************************************************************************//** * @file * @brief EFM32GG_DK3750 board support package * @author Energy Micro AS * @version 1.2.1 ****************************************************************************** * @section License * (C) Copyright 2011 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. * *****************************************************************************/ /***************************************************************************//** * @addtogroup BSP * @{ ******************************************************************************/ #include "efm32.h" #include "efm32_gpio.h" #include "efm32_cmu.h" #include "dvk.h" #include "dvk_bcregisters.h" /** Keep intialization mode */ DVK_Init_TypeDef dvkOperationMode; /**************************************************************************//** * @brief Initialize EMF32GG_DK3750 board support package functionality * @param[in] mode Initialize in EBI or SPI mode *****************************************************************************/ void DVK_init(DVK_Init_TypeDef mode) { bool ret = false; if (mode == DVK_Init_EBI) { dvkOperationMode = mode; DVK_busControlMode(DVK_BusControl_EBI); ret = DVK_EBI_init(); } if (mode == DVK_Init_SPI) { dvkOperationMode = mode; DVK_busControlMode(DVK_BusControl_SPI); ret = DVK_SPI_init(); } if (ret == false) { /* Unable to access board control, this is an abornomal situation. */ /* Try to restart kit and reprogram EFM32 with a standard example */ /* as this is most likely caused by a peripheral misconfiguration. */ while (1) ; } DVK_setEnergyMode(0); } /**************************************************************************//** * @brief Disable EFM32GG_DK3750 board support package functionality *****************************************************************************/ void DVK_disable(void) { if (dvkOperationMode == DVK_Init_EBI) { DVK_EBI_disable(); } if (dvkOperationMode == DVK_Init_SPI) { DVK_SPI_disable(); } DVK_busControlMode(DVK_BusControl_OFF); } /**************************************************************************//** * @brief Configure Board Controller bus decode logic * @param[in] mode Mode of operation for decode logic *****************************************************************************/ void DVK_busControlMode(DVK_BusControl_TypeDef mode) { /* Configure GPIO pins for Board Bus mode */ /* Note: Inverter on GPIO lines to BC, so signals are active low */ CMU_ClockEnable(cmuClock_GPIO, true); switch (mode) { case DVK_BusControl_OFF: /* Configure board for OFF mode on PB15 MCU_EBI_CONNECT */ GPIO_PinModeSet(gpioPortB, 15, gpioModePushPull, 1); /* Configure board for OFF mode on PD13 MCU_SPI_CONNECT */ GPIO_PinModeSet(gpioPortD, 13, gpioModePushPull, 1); break; case DVK_BusControl_DIRECT: /* Configure board for DIRECT on PB15 MCU_EBI_CONNECT */ GPIO_PinModeSet(gpioPortB, 15, gpioModePushPull, 0); /* Configure board for DIRECT on PD13 MCU_SPI_CONNECT */ GPIO_PinModeSet(gpioPortD, 13, gpioModePushPull, 0); break; case DVK_BusControl_SPI: /* Configure board for SPI mode on PB15 MCU_EBI_CONNECT */ GPIO_PinModeSet(gpioPortB, 15, gpioModePushPull, 1); /* Configure board for SPI mode on PD13 MCU_SPI_CONNECT */ GPIO_PinModeSet(gpioPortD, 13, gpioModePushPull, 0); break; case DVK_BusControl_EBI: default: /* Configure board for EBI mode on PB15 MCU_EBI_CONNECT */ GPIO_PinModeSet(gpioPortB, 15, gpioModePushPull, 0); /* Configure board for EBI mode on PD13 MCU_SPI_CONNECT */ GPIO_PinModeSet(gpioPortD, 13, gpioModePushPull, 1); break; } } /**************************************************************************//** * @brief Set board LEDs * * @param[in] leds * 16 bits enabling or disabling individual board LEDs *****************************************************************************/ void DVK_setLEDs(uint16_t leds) { DVK_writeRegister(&BC_REGISTER->UIF_LEDS, leds); } /**************************************************************************//** * @brief Get board LED configuration * * @return * 16 bits of LED status *****************************************************************************/ uint16_t DVK_getLEDs(void) { return DVK_readRegister(&BC_REGISTER->UIF_LEDS); } /**************************************************************************//** * @brief DK3750 Peripheral Access Control * Enable or disable access to on-board peripherals through switches * and SPI switch where applicable * @param[in] perf * Which peripheral to configure * @param[in] enable * If true, sets up access to peripheral, if false disables it *****************************************************************************/ void DVK_peripheralAccess(DVK_Peripheral_TypeDef perf, bool enable) { uint16_t perfControl; perfControl = DVK_readRegister(&BC_REGISTER->PERICON); /* Enable or disable the specificed peripheral by setting board control switch */ if (enable) { switch (perf) { case DVK_RS232_SHUTDOWN: perfControl |= (1 << BC_PERICON_RS232_SHUTDOWN_SHIFT); break; case DVK_RS232_UART: perfControl &= ~(1 << BC_PERICON_RS232_SHUTDOWN_SHIFT); perfControl &= ~(1 << BC_PERICON_RS232_LEUART_SHIFT); perfControl |= (1 << BC_PERICON_RS232_UART_SHIFT); break; case DVK_RS232_LEUART: perfControl &= ~(1 << BC_PERICON_RS232_SHUTDOWN_SHIFT); perfControl &= ~(1 << BC_PERICON_RS232_UART_SHIFT); perfControl |= (1 << BC_PERICON_RS232_LEUART_SHIFT); break; case DVK_I2C: perfControl |= (1 << BC_PERICON_I2C_SHIFT); break; case DVK_ETH: /* Enable SPI interface */ DVK_spiControl(DVK_SPI_Ethernet); /* Enable Ethernet analog switches */ perfControl |= (1 << BC_PERICON_I2S_ETH_SHIFT); perfControl |= (1 << BC_PERICON_I2S_ETH_SEL_SHIFT); break; case DVK_I2S: /* Direct SPI interface to I2S DAC */ DVK_spiControl(DVK_SPI_Audio); /* Also make surea Audio out is connected for I2S operation */ perfControl |= (1 << BC_PERICON_AUDIO_OUT_SHIFT); perfControl |= (1 << BC_PERICON_AUDIO_OUT_SEL_SHIFT); perfControl |= (1 << BC_PERICON_I2S_ETH_SHIFT); perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT); break; case DVK_TRACE: perfControl |= (1 << BC_PERICON_TRACE_SHIFT); break; case DVK_TOUCH: perfControl |= (1 << BC_PERICON_TOUCH_SHIFT); break; case DVK_AUDIO_IN: perfControl |= (1 << BC_PERICON_AUDIO_IN_SHIFT); break; case DVK_AUDIO_OUT: perfControl &= ~(1 << BC_PERICON_AUDIO_OUT_SEL_SHIFT); perfControl |= (1 << BC_PERICON_AUDIO_OUT_SHIFT); break; case DVK_ANALOG_DIFF: perfControl |= (1 << BC_PERICON_ANALOG_DIFF_SHIFT); break; case DVK_ANALOG_SE: perfControl |= (1 << BC_PERICON_ANALOG_SE_SHIFT); break; case DVK_MICROSD: perfControl |= (1 << BC_PERICON_SPI_SHIFT); break; case DVK_TFT: /* Enable SPI to SSD2119 */ DVK_spiControl(DVK_SPI_Display); /* Enable SPI analog switch */ perfControl |= (1 << BC_PERICON_I2S_ETH_SHIFT); break; } } else { switch (perf) { case DVK_RS232_SHUTDOWN: perfControl &= ~(1 << BC_PERICON_RS232_SHUTDOWN_SHIFT); break; case DVK_RS232_UART: perfControl |= (1 << BC_PERICON_RS232_SHUTDOWN_SHIFT); perfControl &= ~(1 << BC_PERICON_RS232_UART_SHIFT); break; case DVK_RS232_LEUART: perfControl |= (1 << BC_PERICON_RS232_SHUTDOWN_SHIFT); perfControl &= ~(1 << BC_PERICON_RS232_LEUART_SHIFT); break; case DVK_I2C: perfControl &= ~(1 << BC_PERICON_I2C_SHIFT); break; case DVK_ETH: /* Enable Ethernet analog switches */ perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT); perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT); break; case DVK_I2S: /* Also make surea Audio out is connected for I2S operation */ perfControl &= ~(1 << BC_PERICON_AUDIO_OUT_SHIFT); perfControl &= ~(1 << BC_PERICON_AUDIO_OUT_SEL_SHIFT); perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT); perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT); break; case DVK_TRACE: perfControl &= ~(1 << BC_PERICON_TRACE_SHIFT); break; case DVK_TOUCH: perfControl &= ~(1 << BC_PERICON_TOUCH_SHIFT); break; case DVK_AUDIO_IN: perfControl &= ~(1 << BC_PERICON_AUDIO_IN_SHIFT); break; case DVK_AUDIO_OUT: perfControl &= ~(1 << BC_PERICON_AUDIO_OUT_SEL_SHIFT); perfControl &= ~(1 << BC_PERICON_AUDIO_OUT_SHIFT); break; case DVK_ANALOG_DIFF: perfControl &= ~(1 << BC_PERICON_ANALOG_DIFF_SHIFT); break; case DVK_ANALOG_SE: perfControl &= ~(1 << BC_PERICON_ANALOG_SE_SHIFT); break; case DVK_MICROSD: perfControl &= ~(1 << BC_PERICON_SPI_SHIFT); break; case DVK_TFT: /* Disable SPI analog switch */ perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT); break; } } /* Write back register */ DVK_writeRegister(&BC_REGISTER->PERICON, perfControl); } /**************************************************************************//** * @brief Get status of push buttons on kit * * @return * Button state, each bit representing each push button PB0-PB4 *****************************************************************************/ uint16_t DVK_getPushButtons(void) { uint16_t tmp; tmp = DVK_readRegister(&BC_REGISTER->UIF_PB); return (~tmp) & 0x000F; } /**************************************************************************//** * @brief Configure SPI for correct peripheral * * @param[in] device * Device to enable SPI bus for *****************************************************************************/ void DVK_spiControl(DVK_SpiControl_TypeDef device) { switch (device) { case DVK_SPI_Audio: DVK_writeRegister(&BC_REGISTER->SPI_DEMUX, BC_SPI_DEMUX_SLAVE_AUDIO); break; case DVK_SPI_Ethernet: DVK_writeRegister(&BC_REGISTER->SPI_DEMUX, BC_SPI_DEMUX_SLAVE_ETHERNET); break; case DVK_SPI_Display: DVK_writeRegister(&BC_REGISTER->SPI_DEMUX, BC_SPI_DEMUX_SLAVE_DISPLAY); break; } } /**************************************************************************//** * @brief Inform AEM/Board Controller about what energy mode we are currently * entering. This information can be used for better visual feedback of * EFM32GG activity for the board controller and PC applications * @param energyMode What energy mode we are going to use next *****************************************************************************/ void DVK_setEnergyMode(uint16_t energyMode) { DVK_writeRegister(&BC_REGISTER->EM, energyMode); } /**************************************************************************//** * @brief Enable "Control" buttons/joystick/dip switch interrupts * @param flags Board control interrupt flags, INTEN_ *****************************************************************************/ void DVK_enableInterrupt(uint16_t flags) { uint16_t tmp; /* Add flags to interrupt enable register */ tmp = DVK_readRegister(&BC_REGISTER->INTEN); tmp |= flags; DVK_writeRegister(&BC_REGISTER->INTEN, tmp); } /**************************************************************************//** * @brief Disable "Control" buttons/joystick/dip switch interrupts * @param flags Board control interrupt flags, BC_INTEN_ *****************************************************************************/ void DVK_disableInterrupt(uint16_t flags) { uint16_t tmp; /* Clear flags from interrupt enable register */ tmp = DVK_readRegister(&BC_REGISTER->INTEN); flags = ~(flags); tmp &= flags; DVK_writeRegister(&BC_REGISTER->INTEN, tmp); } /**************************************************************************//** * @brief Clear interrupts * @param flags Board control interrupt flags, BC_INTEN_ *****************************************************************************/ void DVK_clearInterruptFlags(uint16_t flags) { uint16_t tmp; tmp = DVK_readRegister(&BC_REGISTER->INTFLAG); tmp &= ~(flags); DVK_writeRegister(&BC_REGISTER->INTFLAG, tmp); } /**************************************************************************//** * @brief Read interrupt flags * @return Returns currently triggered interrupts *****************************************************************************/ uint16_t DVK_getInterruptFlags(void) { return DVK_readRegister(&BC_REGISTER->INTFLAG); } /**************************************************************************//** * @brief Get joystick button status * @return Joystick controller status *****************************************************************************/ uint16_t DVK_getJoystick(void) { uint16_t joyStick = 0; joyStick = ~(DVK_readRegister(&BC_REGISTER->UIF_JOYSTICK)) & 0x001f; return joyStick; } /**************************************************************************//** * @brief Get dipswitch status * The DIP switches are free for user programmable purposes * @return Dip switch *****************************************************************************/ uint16_t DVK_getDipSwitch(void) { return DVK_readRegister(&BC_REGISTER->UIF_DIP) & 0x000f; } /**************************************************************************//** * @brief Configure display control *****************************************************************************/ void DVK_displayControl(DVK_Display_TypeDef option) { uint16_t tmp; switch (option) { case DVK_Display_EBI: DVK_writeRegister(&BC_REGISTER->ARB_CTRL, BC_ARB_CTRL_EBI); break; case DVK_Display_SPI: DVK_writeRegister(&BC_REGISTER->ARB_CTRL, BC_ARB_CTRL_SPI); break; case DVK_Display_BC: DVK_writeRegister(&BC_REGISTER->ARB_CTRL, BC_ARB_CTRL_BC); break; case DVK_Display_PowerEnable: tmp = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL); tmp |= (BC_DISPLAY_CTRL_POWER_ENABLE); DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp); break; case DVK_Display_PowerDisable: tmp = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL); tmp &= ~(BC_DISPLAY_CTRL_POWER_ENABLE); DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp); break; case DVK_Display_ResetAssert: tmp = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL); tmp |= (BC_DISPLAY_CTRL_RESET); DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp); break; case DVK_Display_ResetRelease: tmp = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL); tmp &= ~(BC_DISPLAY_CTRL_RESET); DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp); break; case DVK_Display_Mode8080: tmp = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL); tmp &= ~(BC_DISPLAY_CTRL_MODE_GENERIC); DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp); break; case DVK_Display_ModeGeneric: tmp = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL); tmp |= (BC_DISPLAY_CTRL_MODE_GENERIC); DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp); break; default: /* Unknown command */ while (1) ; } } /** @} (end group BSP) */