displaypalemlib.c

Go to the documentation of this file.
00001 /**************************************************************************/
00019 #include <stdint.h>
00020 #include <stdbool.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include "em_device.h"
00025 #include "em_cmu.h"
00026 #include "em_gpio.h"
00027 #include "em_usart.h"
00028 #include "bsp.h"
00029 #include "udelay.h"
00030 
00031 /* DISPLAY driver inclustions */
00032 #include "displayconfigall.h"
00033 #include "displaypal.h"
00034 
00035 #ifdef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE
00036 #include "em_rtc.h"
00037 #ifdef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY
00038 #include "em_prs.h"
00039 #endif
00040 #endif
00041 
00044 /*******************************************************************************
00045  ********************************  STATICS  ************************************
00046  ******************************************************************************/
00047 
00048 #ifdef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE
00049 #ifndef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY
00050 /* GPIO port and pin used for the PAL_GpioPinAutoToggle function. */
00051 static unsigned int gpioPortNo;
00052 static unsigned int gpioPinNo;
00053 #endif
00054 
00055 static void rtcSetup(unsigned int frequency);
00056 #endif
00057 
00058 /*******************************************************************************
00059  **************************     GLOBAL FUNCTIONS      **************************
00060  ******************************************************************************/
00061 
00062 /**************************************************************************/
00071 EMSTATUS PAL_SpiInit (void)
00072 {
00073   EMSTATUS                status    = PAL_EMSTATUS_OK;
00074   USART_InitSync_TypeDef  usartInit = USART_INITSYNC_DEFAULT;
00075 
00076   /* Initialize USART for SPI transaction */
00077   CMU_ClockEnable( PAL_SPI_USART_CLOCK, true );
00078   usartInit.baudrate = PAL_SPI_BAUDRATE;
00079 
00080   USART_InitSync( PAL_SPI_USART_UNIT, &usartInit );
00081 
00082 #if defined( USART_ROUTEPEN_TXPEN )
00083 
00084   PAL_SPI_USART_UNIT->ROUTEPEN = USART_ROUTEPEN_TXPEN
00085     | USART_ROUTEPEN_CLKPEN;
00086   PAL_SPI_USART_UNIT->ROUTELOC0 = ( PAL_SPI_USART_UNIT->ROUTELOC0 &
00087     ~( _USART_ROUTELOC0_TXLOC_MASK | _USART_ROUTELOC0_CLKLOC_MASK ) )
00088     | ( PAL_SPI_USART_LOCATION_TX  << _USART_ROUTELOC0_TXLOC_SHIFT  )
00089     | ( PAL_SPI_USART_LOCATION_SCLK  << _USART_ROUTELOC0_CLKLOC_SHIFT  );
00090 
00091 #else
00092 
00093   PAL_SPI_USART_UNIT->ROUTE = (USART_ROUTE_CLKPEN | USART_ROUTE_TXPEN | PAL_SPI_USART_LOCATION);
00094 
00095 #endif
00096 
00097   return status;
00098 }
00099 
00100 
00101 /**************************************************************************/
00109 EMSTATUS PAL_SpiShutdown (void)
00110 {
00111   EMSTATUS status = PAL_EMSTATUS_OK;
00112 
00113   /* Disable the USART device used for SPI. */
00114   USART_Enable( PAL_SPI_USART_UNIT, usartDisable);
00115 
00116   /* Disable the USART clock. */
00117   CMU_ClockEnable( PAL_SPI_USART_CLOCK, false );
00118 
00119   return status;
00120 }
00121 
00122 
00123 /**************************************************************************/
00131 EMSTATUS PAL_SpiTransmit (uint8_t* data, unsigned int len)
00132 {
00133   EMSTATUS status = PAL_EMSTATUS_OK;
00134 
00135   while (len>0)
00136   {
00137     /* Send only one byte if len==1 or data pointer is not aligned at a 16 bit
00138        word location in memory. */
00139     if ((len == 1) || ((unsigned int)data & 0x1))
00140     {
00141       USART_Tx( PAL_SPI_USART_UNIT, *(uint8_t*)data );
00142       len  --;
00143       data ++;
00144     }
00145     else
00146     {
00147       USART_TxDouble( PAL_SPI_USART_UNIT, *(uint16_t*)data );
00148       len  -= 2;
00149       data += 2;
00150     }
00151   }
00152 
00153   /* Wait for transfer to finish */
00154   while (!(PAL_SPI_USART_UNIT->STATUS & USART_STATUS_TXC)) ;
00155 
00156   return status;
00157 }
00158 
00159 
00160 /**************************************************************************/
00168 EMSTATUS PAL_TimerInit (void)
00169 {
00170   EMSTATUS status = PAL_EMSTATUS_OK;
00171 
00172   UDELAY_Calibrate();
00173 
00174   return status;
00175 }
00176 
00177 
00178 /**************************************************************************/
00186 EMSTATUS PAL_TimerShutdown (void)
00187 {
00188   EMSTATUS status = PAL_EMSTATUS_OK;
00189 
00190   /* Nothing to do since the UDELAY_Delay does not use any resources after
00191      the UDELAY_Calibrate has been called. The UDELAY_Calibrate uses the
00192      RTC to calibrate the delay loop, and restores the RTC after use. */
00193 
00194   return status;
00195 }
00196 
00197 
00198 /**************************************************************************/
00205 EMSTATUS PAL_TimerMicroSecondsDelay(unsigned int usecs)
00206 {
00207   EMSTATUS status = PAL_EMSTATUS_OK;
00208 
00209   UDELAY_Delay(usecs);
00210 
00211   return status;
00212 }
00213 
00214 
00215 #ifdef PAL_TIMER_REPEAT_FUNCTION
00216 /**************************************************************************/
00226 EMSTATUS PAL_TimerRepeat (void(*pFunction)(void*),
00227                             void* argument,
00228                             unsigned int frequency)
00229 {
00230   if (0 != PAL_TIMER_REPEAT_FUNCTION(pFunction, argument, frequency))
00231     return PAL_EMSTATUS_REPEAT_FAILED;
00232   else
00233     return EMSTATUS_OK;
00234 }
00235 #endif
00236 
00237 
00238 /**************************************************************************/
00246 EMSTATUS PAL_GpioInit (void)
00247 {
00248   EMSTATUS status = PAL_EMSTATUS_OK;
00249 
00250   /* Enable the GPIO clock in order to access the GPIO module. */
00251   CMU_ClockEnable( cmuClock_GPIO, true );
00252 
00253   return status;
00254 }
00255 
00256 
00257 /**************************************************************************/
00265 EMSTATUS PAL_GpioShutdown (void)
00266 {
00267   EMSTATUS status = PAL_EMSTATUS_OK;
00268 
00269   /* Enable the GPIO clock in order to access the GPIO module. */
00270   CMU_ClockEnable( cmuClock_GPIO, false );
00271 
00272   return status;
00273 }
00274 
00275 
00276 /***************************************************************************/
00295 EMSTATUS PAL_GpioPinModeSet(unsigned int   port,
00296                             unsigned int   pin,
00297                             PAL_GpioMode_t mode,
00298                             unsigned int   platformSpecific)
00299 {
00300   EMSTATUS status = PAL_EMSTATUS_OK;
00301   GPIO_Mode_TypeDef   emGpioMode;
00302 
00303   /* Convert PAL pin mode to GPIO_Mode_TypeDef defined in em_gpio.h.  */
00304   switch (mode)
00305   {
00306   case palGpioModePushPull:
00307     emGpioMode = gpioModePushPull;
00308     break;
00309   default:
00310     return PAL_EMSTATUS_INVALID_PARAM;
00311   }
00312 
00313   GPIO_PinModeSet((GPIO_Port_TypeDef) port, pin, emGpioMode, platformSpecific);
00314 
00315   return status;
00316 }
00317 
00318 
00319 /***************************************************************************/
00334 EMSTATUS PAL_GpioPinOutSet(unsigned int port, unsigned int pin)
00335 {
00336   EMSTATUS status = PAL_EMSTATUS_OK;
00337 
00338   GPIO_PinOutSet((GPIO_Port_TypeDef) port, pin);
00339 
00340   return status;
00341 }
00342 
00343 
00344 /***************************************************************************/
00359 EMSTATUS PAL_GpioPinOutClear(unsigned int port, unsigned int pin)
00360 {
00361   EMSTATUS status = PAL_EMSTATUS_OK;
00362 
00363   GPIO_PinOutClear((GPIO_Port_TypeDef) port, pin);
00364 
00365   return status;
00366 }
00367 
00368 
00369 /***************************************************************************/
00384 EMSTATUS PAL_GpioPinOutToggle(unsigned int port, unsigned int pin)
00385 {
00386   EMSTATUS status = PAL_EMSTATUS_OK;
00387 
00388   GPIO_PinOutToggle((GPIO_Port_TypeDef) port, pin);
00389 
00390   return status;
00391 }
00392 
00393 
00394 #ifdef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE
00395 /**************************************************************************/
00403 EMSTATUS PAL_GpioPinAutoToggle (unsigned int gpioPort,
00404                                 unsigned int gpioPin,
00405                                 unsigned int frequency)
00406 {
00407   EMSTATUS status = EMSTATUS_OK;
00408 
00409 #ifdef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY
00410 
00411 #if defined( BSP_STK_2010 )
00412   /* We only support auto HW toggling on GPIO port E pin 10 on Zero STK.  */
00413   if ( (gpioPortE != gpioPort) || (10 != gpioPin) )
00414 
00415 #elif defined( BSP_STK_2011 )
00416   /* We only support auto HW toggling on GPIO port F pin 3 on Happy STK.  */
00417   if ( (gpioPortF != gpioPort) || (3 != gpioPin) )
00418 
00419 #else
00420 #error "Illegal display auto-toggle setup."
00421 #endif
00422   {
00423     status = PAL_EMSTATUS_INVALID_PARAM;
00424   }
00425   else
00426   {
00427     /* Setup PRS to drive the GPIO port E pin 10 which is connected to the
00428        display com inversion pin (EXTCOMIN) using the RTC COMP0 signal as
00429        source. */
00430     uint32_t     source  = PRS_CH_CTRL_SOURCESEL_RTC;
00431     uint32_t     signal  = PRS_CH_CTRL_SIGSEL_RTCCOMP0;
00432 
00433     /* Enable PRS clock */
00434     CMU_ClockEnable(cmuClock_PRS, true);
00435 
00436     /* Set up PRS to trigger from an RTC compare match */
00437     PRS_SourceAsyncSignalSet(LCD_AUTO_TOGGLE_PRS_CH, source, signal);
00438 
00439     /* This outputs the PRS pulse on PE10 which is the EXTCOMIN pin */
00440     PRS->ROUTE = ( PRS->ROUTE & ~_PRS_ROUTE_LOCATION_MASK )
00441                  | LCD_AUTO_TOGGLE_PRS_ROUTE_LOC;
00442     PRS->ROUTE |= LCD_AUTO_TOGGLE_PRS_ROUTE_PEN;
00443   }
00444 #else
00445   /* Store GPIO pin data. */
00446   gpioPortNo = gpioPort;
00447   gpioPinNo  = gpioPin;
00448 #endif
00449 
00450   if (EMSTATUS_OK == status)
00451   {
00452     /* Setup GPIO pin. */
00453     GPIO_PinModeSet((GPIO_Port_TypeDef)gpioPort, gpioPin, gpioModePushPull, 0 );
00454 
00455     /* Setup RTC to to toggle PRS or generate interrupts at given frequency. */
00456     rtcSetup(frequency);
00457   }
00458 
00459   return status;
00460 }
00461 
00462 
00463 #ifdef  INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE
00464 #ifndef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY
00465 /**************************************************************************/
00470 void RTC_IRQHandler(void)
00471 {
00472   /* Clear interrupt source */
00473   RTC_IntClear(RTC_IF_COMP0);
00474 
00475   /* Toggle GPIO pin. */
00476   GPIO_PinOutToggle((GPIO_Port_TypeDef)gpioPortNo, gpioPinNo );
00477 }
00478 #endif
00479 #endif
00480 
00481 
00482 /**************************************************************************/
00486 static void rtcSetup(unsigned int frequency)
00487 {
00488   RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT;
00489 
00490   /* Enable LE domain registers */
00491   if ( !( CMU->HFCORECLKEN0 & CMU_HFCORECLKEN0_LE) )
00492   {
00493     CMU_ClockEnable(cmuClock_CORELE, true);
00494   }
00495 
00496 #ifdef PAL_RTC_CLOCK_LFXO
00497   /* LFA with LFXO setup is relatively time consuming. Therefore, check if it
00498      already enabled before calling. */
00499   if ( !(CMU->STATUS & CMU_STATUS_LFXOENS) )
00500   {
00501     CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
00502   }
00503   if ( cmuSelect_LFXO != CMU_ClockSelectGet(cmuClock_LFA) )
00504   {
00505     CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO);
00506   }
00507 #elif defined PAL_RTC_CLOCK_LFRCO
00508   /* Enable LFACLK in CMU (will also enable LFRCO oscillator if not enabled) */
00509   CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO);
00510 #elif defined PAL_RTC_CLOCK_ULFRCO
00511   /* Enable LFACLK in CMU (will also enable ULFRCO oscillator if not enabled) */
00512   CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_ULFRCO);
00513 #else
00514 #error No clock source for RTC defined.
00515 #endif
00516 
00517   /* Set the prescaler. */
00518   CMU_ClockDivSet( cmuClock_RTC, cmuClkDiv_2 );
00519 
00520   /* Enable RTC clock */
00521   CMU_ClockEnable(cmuClock_RTC, true);
00522 
00523   /* Initialize RTC */
00524   rtcInit.enable   = false;  /* Do not start RTC after initialization is complete. */
00525   rtcInit.debugRun = false;  /* Halt RTC when debugging. */
00526   rtcInit.comp0Top = true;   /* Wrap around on COMP0 match. */
00527   RTC_Init(&rtcInit);
00528 
00529   /* Interrupt at given frequency. */
00530   RTC_CompareSet(0, (CMU_ClockFreqGet(cmuClock_RTC) / frequency) - 1 );
00531 
00532 #ifndef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY
00533   /* Enable interrupt */
00534   NVIC_EnableIRQ(RTC_IRQn);
00535   RTC_IntEnable(RTC_IEN_COMP0);
00536 #endif
00537 
00538   /* Start Counter */
00539   RTC_Enable(true);
00540 }
00541 #endif  /* INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE */
00542