1 /**************************************************************************//**
2  * @file
3  * @brief EFM32GG_DK3750 board support package
4  * @author Energy Micro AS
5  * @version 2.0.1
6  ******************************************************************************
7  * @section License
8  * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
9  *******************************************************************************
10  *
11  * Permission is granted to anyone to use this software for any purpose,
12  * including commercial applications, and to alter it and redistribute it
13  * freely, subject to the following restrictions:
14  *
15  * 1. The origin of this software must not be misrepresented; you must not
16  *    claim that you wrote the original software.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  *    misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  * 4. The source and compiled code may only be used on Energy Micro "EFM32"
21  *    microcontrollers and "EFR4" radios.
22  *
23  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
24  * obligation to support this Software. Energy Micro AS is providing the
25  * Software "AS IS", with no express or implied warranties of any kind,
26  * including, but not limited to, any implied warranties of merchantability
27  * or fitness for any particular purpose or warranties against infringement
28  * of any proprietary rights of a third party.
29  *
30  * Energy Micro AS will not be liable for any consequential, incidental, or
31  * special damages, or any other relief, or for any claim by any third party,
32  * arising from your use of this Software.
33  *
34  *****************************************************************************/
35 
36 /**************************************************************************//**
37  * @addtogroup BSP
38  * @{
39  *****************************************************************************/
40 
41 #include "efm32.h"
42 #include "em_gpio.h"
43 #include "em_cmu.h"
44 #include "em_usart.h"
45 #include "dvk.h"
46 #include "dvk_bcregisters.h"
47 
48 /** Keep intialization mode */
49 DVK_Init_TypeDef dvkOperationMode;
50 
51 /**************************************************************************//**
52  * @brief Initialize EFM32GG_DK3750 board support package functionality
53  * @param[in] mode Initialize in EBI or SPI mode
54  *****************************************************************************/
DVK_init(DVK_Init_TypeDef mode)55 void DVK_init(DVK_Init_TypeDef mode)
56 {
57   bool ret = false;
58 
59   if (mode == DVK_Init_EBI)
60   {
61     dvkOperationMode = mode;
62     DVK_busControlMode(DVK_BusControl_EBI);
63     ret = DVK_EBI_init();
64   }
65   if (mode == DVK_Init_SPI)
66   {
67     dvkOperationMode = mode;
68     DVK_busControlMode(DVK_BusControl_SPI);
69     ret = DVK_SPI_init();
70   }
71 
72   if (ret == false)
73   {
74     /* Unable to access board control, this is an abornomal situation. */
75     /* Try to restart kit and reprogram EFM32 with a standard example */
76     /* as this is most likely caused by a peripheral misconfiguration. */
77     while (1) ;
78   }
79 
80   DVK_setEnergyMode(0);
81 }
82 
83 
84 /**************************************************************************//**
85  * @brief Disable EFM32GG_DK3750 board support package functionality
86  *****************************************************************************/
DVK_disable(void)87 void DVK_disable(void)
88 {
89   if (dvkOperationMode == DVK_Init_EBI)
90   {
91     DVK_EBI_disable();
92   }
93   if (dvkOperationMode == DVK_Init_SPI)
94   {
95     DVK_SPI_disable();
96   }
97   DVK_busControlMode(DVK_BusControl_OFF);
98 }
99 
100 
101 /**************************************************************************//**
102  * @brief Configure Board Controller bus decode logic
103  * @param[in] mode Mode of operation for decode logic
104  *****************************************************************************/
DVK_busControlMode(DVK_BusControl_TypeDef mode)105 void DVK_busControlMode(DVK_BusControl_TypeDef mode)
106 {
107   /* Configure GPIO pins for Board Bus mode */
108   /* Note: Inverter on GPIO lines to BC, so signals are active low */
109   CMU_ClockEnable(cmuClock_GPIO, true);
110 
111   switch (mode)
112   {
113   case DVK_BusControl_OFF:
114     /* Configure board for OFF mode on PB15 MCU_EBI_CONNECT */
115     GPIO_PinModeSet(gpioPortB, 15, gpioModePushPull, 1);
116     /* Configure board for OFF mode on PD13 MCU_SPI_CONNECT */
117     GPIO_PinModeSet(gpioPortD, 13, gpioModePushPull, 1);
118     break;
119   case DVK_BusControl_DIRECT:
120     /* Configure board for DIRECT on PB15 MCU_EBI_CONNECT */
121     GPIO_PinModeSet(gpioPortB, 15, gpioModePushPull, 0);
122     /* Configure board for DIRECT on PD13 MCU_SPI_CONNECT */
123     GPIO_PinModeSet(gpioPortD, 13, gpioModePushPull, 0);
124     break;
125   case DVK_BusControl_SPI:
126     /* Configure board for SPI mode on PB15 MCU_EBI_CONNECT */
127     GPIO_PinModeSet(gpioPortB, 15, gpioModePushPull, 1);
128     /* Configure board for SPI mode on PD13 MCU_SPI_CONNECT */
129     GPIO_PinModeSet(gpioPortD, 13, gpioModePushPull, 0);
130     break;
131   case DVK_BusControl_EBI:
132   default:
133     /* Configure board for EBI mode on PB15 MCU_EBI_CONNECT */
134     GPIO_PinModeSet(gpioPortB, 15, gpioModePushPull, 0);
135     /* Configure board for EBI mode on PD13 MCU_SPI_CONNECT */
136     GPIO_PinModeSet(gpioPortD, 13, gpioModePushPull, 1);
137     break;
138   }
139 }
140 
141 
142 /**************************************************************************//**
143  * @brief Set board LEDs
144  *
145  * @param[in] leds
146  *    16 bits enabling or disabling individual board LEDs
147  *****************************************************************************/
DVK_setLEDs(uint16_t leds)148 void DVK_setLEDs(uint16_t leds)
149 {
150   DVK_writeRegister(&BC_REGISTER->UIF_LEDS, leds);
151 }
152 
153 
154 /**************************************************************************//**
155  * @brief Get board LED configuration
156  *
157  * @return
158  *    16 bits of LED status
159  *****************************************************************************/
DVK_getLEDs(void)160 uint16_t DVK_getLEDs(void)
161 {
162   return DVK_readRegister(&BC_REGISTER->UIF_LEDS);
163 }
164 
165 
166 /**************************************************************************//**
167  * @brief DK3750 Peripheral Access Control
168  *    Enable or disable access to on-board peripherals through switches
169  *    and SPI switch where applicable. Turn off conflicting peripherals when
170  *    enabling another.
171  * @param[in] perf
172  *    Which peripheral to configure
173  * @param[in] enable
174  *    If true, sets up access to peripheral, if false disables it
175  *****************************************************************************/
DVK_peripheralAccess(DVK_Peripheral_TypeDef perf,bool enable)176 void DVK_peripheralAccess(DVK_Peripheral_TypeDef perf, bool enable)
177 {
178   uint16_t perfControl;
179 
180   perfControl = DVK_readRegister(&BC_REGISTER->PERICON);
181 
182   /* Enable or disable the specificed peripheral by setting board control switch */
183   if (enable)
184   {
185     switch (perf)
186     {
187     case DVK_RS232_SHUTDOWN:
188       perfControl |= (1 << BC_PERICON_RS232_SHUTDOWN_SHIFT);
189       break;
190 
191     case DVK_RS232_UART:
192       perfControl &= ~(1 << BC_PERICON_RS232_SHUTDOWN_SHIFT);
193       perfControl &= ~(1 << BC_PERICON_RS232_LEUART_SHIFT);
194       perfControl |= (1 << BC_PERICON_RS232_UART_SHIFT);
195       break;
196 
197     case DVK_RS232_LEUART:
198       perfControl &= ~(1 << BC_PERICON_RS232_SHUTDOWN_SHIFT);
199       perfControl &= ~(1 << BC_PERICON_RS232_UART_SHIFT);
200       perfControl |= (1 << BC_PERICON_RS232_LEUART_SHIFT);
201       break;
202 
203     case DVK_I2C:
204       perfControl |= (1 << BC_PERICON_I2C_SHIFT);
205       break;
206 
207     case DVK_ETH:
208       /* Enable SPI interface */
209       DVK_spiControl(DVK_SPI_Ethernet);
210 
211       /* Enable Ethernet analog switches */
212       perfControl |= (1 << BC_PERICON_I2S_ETH_SHIFT);
213       perfControl |= (1 << BC_PERICON_I2S_ETH_SEL_SHIFT);
214 
215       /* Disable Analog Diff Input - pins PD0 and PD1 is shared */
216       perfControl &= ~(1 << BC_PERICON_ANALOG_DIFF_SHIFT);
217       /* Disable Touch Inputs - pin PD3 is shared */
218       perfControl &= ~(1 << BC_PERICON_TOUCH_SHIFT);
219       /* Disable Analog SE Input - pin PD2 is shared */
220       perfControl &= ~(1 << BC_PERICON_ANALOG_SE_SHIFT);
221       break;
222 
223     case DVK_I2S:
224       /* Direct SPI interface to I2S DAC */
225       DVK_spiControl(DVK_SPI_Audio);
226 
227       /* Also make surea Audio out is connected for I2S operation */
228       perfControl |= (1 << BC_PERICON_AUDIO_OUT_SHIFT);
229       perfControl |= (1 << BC_PERICON_AUDIO_OUT_SEL_SHIFT);
230       perfControl |= (1 << BC_PERICON_I2S_ETH_SHIFT);
231       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT);
232 
233       /* Disable Analog Diff Input - pins PD0 and PD1 is shared */
234       perfControl &= ~(1 << BC_PERICON_ANALOG_DIFF_SHIFT);
235       /* Disable Touch Inputs - pin PD3 is shared */
236       perfControl &= ~(1 << BC_PERICON_TOUCH_SHIFT);
237       /* Disable Analog SE Input - pin PD2 is shared */
238       perfControl &= ~(1 << BC_PERICON_ANALOG_SE_SHIFT);
239       break;
240 
241     case DVK_TRACE:
242       perfControl |= (1 << BC_PERICON_TRACE_SHIFT);
243       break;
244 
245     case DVK_TOUCH:
246       perfControl |= (1 << BC_PERICON_TOUCH_SHIFT);
247       /* Disconnect SPI switch, pin PD3 is shared */
248       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT);
249       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT);
250       DVK_spiControl(DVK_SPI_OFF);
251       break;
252 
253     case DVK_AUDIO_IN:
254       perfControl |= (1 << BC_PERICON_AUDIO_IN_SHIFT);
255       break;
256 
257     case DVK_AUDIO_OUT:
258       perfControl &= ~(1 << BC_PERICON_AUDIO_OUT_SEL_SHIFT);
259       perfControl |= (1 << BC_PERICON_AUDIO_OUT_SHIFT);
260       break;
261 
262     case DVK_ANALOG_DIFF:
263       perfControl |= (1 << BC_PERICON_ANALOG_DIFF_SHIFT);
264       /* Disconnect SPI switch, pin PD0 and PD1 is shared */
265       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT);
266       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT);
267       DVK_spiControl(DVK_SPI_OFF);
268       break;
269 
270     case DVK_ANALOG_SE:
271       perfControl |= (1 << BC_PERICON_ANALOG_SE_SHIFT);
272       /* Disconnect SPI switch, pin PD2 is shared */
273       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT);
274       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT);
275       DVK_spiControl(DVK_SPI_OFF);
276       break;
277 
278     case DVK_MICROSD:
279       perfControl |= (1 << BC_PERICON_SPI_SHIFT);
280       break;
281 
282     case DVK_TFT:
283       /* Enable SPI to SSD2119 */
284       DVK_spiControl(DVK_SPI_Display);
285       /* Enable SPI analog switch */
286       perfControl |= (1 << BC_PERICON_I2S_ETH_SHIFT);
287       /* Disable Analog Diff Input - pins D0 and D1 is shared */
288       perfControl &= ~(1 << BC_PERICON_ANALOG_DIFF_SHIFT);
289       /* Disable Touch Inputs - pin D3 is shared */
290       perfControl &= ~(1 << BC_PERICON_TOUCH_SHIFT);
291       /* Disable Analog SE Input - pin D2 is shared */
292       perfControl &= ~(1 << BC_PERICON_ANALOG_SE_SHIFT);
293       break;
294     }
295   }
296   else
297   {
298     switch (perf)
299     {
300     case DVK_RS232_SHUTDOWN:
301       perfControl &= ~(1 << BC_PERICON_RS232_SHUTDOWN_SHIFT);
302       break;
303 
304     case DVK_RS232_UART:
305       perfControl |= (1 << BC_PERICON_RS232_SHUTDOWN_SHIFT);
306       perfControl &= ~(1 << BC_PERICON_RS232_UART_SHIFT);
307       break;
308 
309     case DVK_RS232_LEUART:
310       perfControl |= (1 << BC_PERICON_RS232_SHUTDOWN_SHIFT);
311       perfControl &= ~(1 << BC_PERICON_RS232_LEUART_SHIFT);
312       break;
313 
314     case DVK_I2C:
315       perfControl &= ~(1 << BC_PERICON_I2C_SHIFT);
316       break;
317 
318     case DVK_ETH:
319       /* Disable SPI interface */
320       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT);
321       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT);
322       DVK_spiControl(DVK_SPI_OFF);
323       break;
324 
325     case DVK_I2S:
326       /* Disable SPI interface and audio out */
327       perfControl &= ~(1 << BC_PERICON_AUDIO_OUT_SHIFT);
328       perfControl &= ~(1 << BC_PERICON_AUDIO_OUT_SEL_SHIFT);
329       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT);
330       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT);
331       DVK_spiControl(DVK_SPI_OFF);
332       break;
333 
334     case DVK_TRACE:
335       perfControl &= ~(1 << BC_PERICON_TRACE_SHIFT);
336       break;
337 
338     case DVK_TOUCH:
339       perfControl &= ~(1 << BC_PERICON_TOUCH_SHIFT);
340       break;
341 
342     case DVK_AUDIO_IN:
343       perfControl &= ~(1 << BC_PERICON_AUDIO_IN_SHIFT);
344       break;
345 
346     case DVK_AUDIO_OUT:
347       perfControl &= ~(1 << BC_PERICON_AUDIO_OUT_SEL_SHIFT);
348       perfControl &= ~(1 << BC_PERICON_AUDIO_OUT_SHIFT);
349       break;
350 
351     case DVK_ANALOG_DIFF:
352       perfControl &= ~(1 << BC_PERICON_ANALOG_DIFF_SHIFT);
353       break;
354 
355     case DVK_ANALOG_SE:
356       perfControl &= ~(1 << BC_PERICON_ANALOG_SE_SHIFT);
357       break;
358 
359     case DVK_MICROSD:
360       perfControl &= ~(1 << BC_PERICON_SPI_SHIFT);
361       break;
362 
363     case DVK_TFT:
364       /* Disable SPI interface */
365       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SHIFT);
366       perfControl &= ~(1 << BC_PERICON_I2S_ETH_SEL_SHIFT);
367       DVK_spiControl(DVK_SPI_OFF);
368       break;
369     }
370   }
371   /* Write back register */
372   DVK_writeRegister(&BC_REGISTER->PERICON, perfControl);
373 }
374 
375 
376 /**************************************************************************//**
377  * @brief Get status of push buttons on kit
378  *
379  * @return
380  *    Button state, each bit representing each push button PB0-PB4
381  *****************************************************************************/
DVK_getPushButtons(void)382 uint16_t DVK_getPushButtons(void)
383 {
384   uint16_t tmp;
385 
386   tmp = DVK_readRegister(&BC_REGISTER->UIF_PB);
387 
388   return (~tmp) & 0x000F;
389 }
390 
391 
392 /**************************************************************************//**
393  * @brief Configure SPI for correct peripheral
394  *
395  * @param[in] device
396  *    Device to enable SPI bus for
397  *****************************************************************************/
DVK_spiControl(DVK_SpiControl_TypeDef device)398 void DVK_spiControl(DVK_SpiControl_TypeDef device)
399 {
400   switch (device)
401   {
402   case DVK_SPI_Audio:
403     DVK_writeRegister(&BC_REGISTER->SPI_DEMUX, BC_SPI_DEMUX_SLAVE_AUDIO);
404     break;
405 
406   case DVK_SPI_Ethernet:
407     DVK_writeRegister(&BC_REGISTER->SPI_DEMUX, BC_SPI_DEMUX_SLAVE_ETHERNET);
408     break;
409 
410   case DVK_SPI_Display:
411     DVK_writeRegister(&BC_REGISTER->SPI_DEMUX, BC_SPI_DEMUX_SLAVE_DISPLAY);
412     break;
413 
414   case DVK_SPI_OFF:
415     USART_Reset(USART1);
416     CMU_ClockEnable(cmuClock_USART1, false);
417     break;
418   }
419 }
420 
421 
422 /**************************************************************************//**
423  * @brief Inform AEM/Board Controller about what energy mode we are currently
424  *        entering. This information can be used for better visual feedback of
425  *        EFM32GG activity for the board controller and PC applications
426  * @param energyMode What energy mode we are going to use next
427  *****************************************************************************/
DVK_setEnergyMode(uint16_t energyMode)428 void DVK_setEnergyMode(uint16_t energyMode)
429 {
430   DVK_writeRegister(&BC_REGISTER->EM, energyMode);
431 }
432 
433 
434 /**************************************************************************//**
435  * @brief Enable "Control" buttons/joystick/dip switch interrupts
436  * @param flags Board control interrupt flags, INTEN_<something>
437  *****************************************************************************/
DVK_enableInterrupt(uint16_t flags)438 void DVK_enableInterrupt(uint16_t flags)
439 {
440   uint16_t tmp;
441 
442   /* Add flags to interrupt enable register */
443   tmp  = DVK_readRegister(&BC_REGISTER->INTEN);
444   tmp |= flags;
445   DVK_writeRegister(&BC_REGISTER->INTEN, tmp);
446 }
447 
448 
449 /**************************************************************************//**
450  * @brief Disable "Control" buttons/joystick/dip switch interrupts
451  * @param flags Board control interrupt flags, BC_INTEN_<something>
452  *****************************************************************************/
DVK_disableInterrupt(uint16_t flags)453 void DVK_disableInterrupt(uint16_t flags)
454 {
455   uint16_t tmp;
456 
457   /* Clear flags from interrupt enable register */
458   tmp   = DVK_readRegister(&BC_REGISTER->INTEN);
459   flags = ~(flags);
460   tmp  &= flags;
461   DVK_writeRegister(&BC_REGISTER->INTEN, tmp);
462 }
463 
464 
465 /**************************************************************************//**
466  * @brief Clear interrupts
467  * @param flags Board control interrupt flags, BC_INTEN_<something>
468  *****************************************************************************/
DVK_clearInterruptFlags(uint16_t flags)469 void DVK_clearInterruptFlags(uint16_t flags)
470 {
471   uint16_t tmp;
472   tmp  = DVK_readRegister(&BC_REGISTER->INTFLAG);
473   tmp &= ~(flags);
474   DVK_writeRegister(&BC_REGISTER->INTFLAG, tmp);
475 }
476 
477 
478 /**************************************************************************//**
479  * @brief Read interrupt flags
480  * @return Returns currently triggered interrupts
481  *****************************************************************************/
DVK_getInterruptFlags(void)482 uint16_t DVK_getInterruptFlags(void)
483 {
484   return DVK_readRegister(&BC_REGISTER->INTFLAG);
485 }
486 
487 
488 /**************************************************************************//**
489  * @brief Get joystick button status
490  * @return Joystick controller status
491  *****************************************************************************/
DVK_getJoystick(void)492 uint16_t DVK_getJoystick(void)
493 {
494   uint16_t joyStick = 0;
495 
496   joyStick = ~(DVK_readRegister(&BC_REGISTER->UIF_JOYSTICK)) & 0x001f;
497 
498   return joyStick;
499 }
500 
501 
502 /**************************************************************************//**
503  * @brief Get dipswitch status
504  *        The DIP switches are free for user programmable purposes
505  * @return Dip switch
506  *****************************************************************************/
DVK_getDipSwitch(void)507 uint16_t DVK_getDipSwitch(void)
508 {
509   return DVK_readRegister(&BC_REGISTER->UIF_DIP) & 0x000f;
510 }
511 
512 
513 /**************************************************************************//**
514  * @brief Configure display control
515  *****************************************************************************/
DVK_displayControl(DVK_Display_TypeDef option)516 void DVK_displayControl(DVK_Display_TypeDef option)
517 {
518   uint16_t tmp;
519 
520   switch (option)
521   {
522   case DVK_Display_EBI:
523     DVK_writeRegister(&BC_REGISTER->ARB_CTRL, BC_ARB_CTRL_EBI);
524     break;
525 
526   case DVK_Display_SPI:
527     DVK_writeRegister(&BC_REGISTER->ARB_CTRL, BC_ARB_CTRL_SPI);
528     break;
529 
530   case DVK_Display_BC:
531     DVK_writeRegister(&BC_REGISTER->ARB_CTRL, BC_ARB_CTRL_BC);
532     break;
533 
534   case DVK_Display_PowerEnable:
535     tmp  = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL);
536     tmp |= (BC_DISPLAY_CTRL_POWER_ENABLE);
537     DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp);
538     break;
539 
540   case DVK_Display_PowerDisable:
541     tmp  = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL);
542     tmp &= ~(BC_DISPLAY_CTRL_POWER_ENABLE);
543     DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp);
544     break;
545 
546   case DVK_Display_ResetAssert:
547     tmp  = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL);
548     tmp |= (BC_DISPLAY_CTRL_RESET);
549     DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp);
550     break;
551 
552   case DVK_Display_ResetRelease:
553     tmp  = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL);
554     tmp &= ~(BC_DISPLAY_CTRL_RESET);
555     DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp);
556     break;
557 
558   case DVK_Display_Mode8080:
559     tmp  = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL);
560     tmp &= ~(BC_DISPLAY_CTRL_MODE_GENERIC);
561     DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp);
562     break;
563 
564   case DVK_Display_ModeGeneric:
565     tmp  = DVK_readRegister(&BC_REGISTER->DISPLAY_CTRL);
566     tmp |= (BC_DISPLAY_CTRL_MODE_GENERIC);
567     DVK_writeRegister(&BC_REGISTER->DISPLAY_CTRL, tmp);
568     break;
569 
570   default:
571     /* Unknown command */
572     while (1) ;
573   }
574 }
575 
576 /** @} (end group BSP) */
577