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