/**************************************************************************//** * @file * @brief EFM32GG_DK3750 board support package * @author Energy Micro AS * @version 2.0.1 ****************************************************************************** * @section License * (C) Copyright 2012 Energy Micro AS, http://www.energymicro.com ******************************************************************************* * * 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. * 4. The source and compiled code may only be used on Energy Micro "EFM32" * microcontrollers and "EFR4" radios. * * 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 "em_gpio.h" #include "em_cmu.h" #include "em_usart.h" #include "dvk.h" #include "dvk_bcregisters.h" /** Keep intialization mode */ DVK_Init_TypeDef dvkOperationMode; /**************************************************************************//** * @brief Initialize EFM32GG_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. Turn off conflicting peripherals when * enabling another. * @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); /* Disable Analog Diff Input - pins PD0 and PD1 is shared */ perfControl &= ~(1 << BC_PERICON_ANALOG_DIFF_SHIFT); /* Disable Touch Inputs - pin PD3 is shared */ perfControl &= ~(1 << BC_PERICON_TOUCH_SHIFT); /* Disable Analog SE Input - pin PD2 is shared */ perfControl &= ~(1 << BC_PERICON_ANALOG_SE_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); /* Disable Analog Diff Input - pins PD0 and PD1 is shared */ perfControl &= ~(1 << BC_PERICON_ANALOG_DIFF_SHIFT); /* Disable Touch Inputs - pin PD3 is shared */ perfControl &= ~(1 << BC_PERICON_TOUCH_SHIFT); /* Disable Analog SE Input - pin PD2 is shared */ perfControl &= ~(1 << BC_PERICON_ANALOG_SE_SHIFT); break; case DVK_TRACE: perfControl |= (1 << BC_PERICON_TRACE_SHIFT); break; case DVK_TOUCH: perfControl |= (1 << BC_PERICON_TOUCH_SHIFT); /* Disconnect SPI switch, pin PD3 is shared */ perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT); perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT); DVK_spiControl(DVK_SPI_OFF); 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); /* Disconnect SPI switch, pin PD0 and PD1 is shared */ perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT); perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT); DVK_spiControl(DVK_SPI_OFF); break; case DVK_ANALOG_SE: perfControl |= (1 << BC_PERICON_ANALOG_SE_SHIFT); /* Disconnect SPI switch, pin PD2 is shared */ perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT); perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT); DVK_spiControl(DVK_SPI_OFF); 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); /* Disable Analog Diff Input - pins D0 and D1 is shared */ perfControl &= ~(1 << BC_PERICON_ANALOG_DIFF_SHIFT); /* Disable Touch Inputs - pin D3 is shared */ perfControl &= ~(1 << BC_PERICON_TOUCH_SHIFT); /* Disable Analog SE Input - pin D2 is shared */ perfControl &= ~(1 << BC_PERICON_ANALOG_SE_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: /* Disable SPI interface */ perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT); perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT); DVK_spiControl(DVK_SPI_OFF); break; case DVK_I2S: /* Disable SPI interface and audio out */ 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); DVK_spiControl(DVK_SPI_OFF); 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 interface */ perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT); perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT); DVK_spiControl(DVK_SPI_OFF); 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; case DVK_SPI_OFF: USART_Reset(USART1); CMU_ClockEnable(cmuClock_USART1, false); 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) */