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 "udelay.h"
00029 
00030 /* DISPLAY driver inclustions */
00031 #include "displayconfigall.h"
00032 #include "displaypal.h"
00033 
00034 #ifdef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE
00035 #include "em_rtc.h"
00036 #ifdef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY
00037 #include "em_prs.h"
00038 #endif
00039 #endif
00040 
00043 /*******************************************************************************
00044  ********************************  STATICS  ************************************
00045  ******************************************************************************/
00046 
00047 #ifdef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE
00048 #ifndef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY
00049 /* GPIO port and pin used for the PAL_GpioPinAutoToggle function. */
00050 static unsigned int gpioPortNo;
00051 static unsigned int gpioPinNo;
00052 #endif
00053 
00054 static void rtcSetup(unsigned int frequency);
00055 #endif
00056 
00057 /*******************************************************************************
00058  **************************     GLOBAL FUNCTIONS      **************************
00059  ******************************************************************************/
00060 
00061 /**************************************************************************/
00070 EMSTATUS PAL_SpiInit (void)
00071 {
00072   EMSTATUS                status    = PAL_EMSTATUS_OK;
00073   USART_InitSync_TypeDef  usartInit = USART_INITSYNC_DEFAULT;
00074 
00075   /* Initialize USART for SPI transaction */
00076   CMU_ClockEnable( PAL_SPI_USART_CLOCK, true );
00077   usartInit.baudrate = PAL_SPI_BAUDRATE;
00078   
00079   USART_InitSync( PAL_SPI_USART_UNIT, &usartInit );
00080   PAL_SPI_USART_UNIT->ROUTE = (USART_ROUTE_CLKPEN | USART_ROUTE_TXPEN | PAL_SPI_USART_LOCATION);
00081 
00082   return status;
00083 }
00084 
00085 
00086 /**************************************************************************/
00094 EMSTATUS PAL_SpiShutdown (void)
00095 {
00096   EMSTATUS status = PAL_EMSTATUS_OK;
00097 
00098   /* Disable the USART device used for SPI. */
00099   USART_Enable( PAL_SPI_USART_UNIT, usartDisable);
00100 
00101   /* Disable the USART clock. */
00102   CMU_ClockEnable( PAL_SPI_USART_CLOCK, false );
00103 
00104   return status;
00105 }
00106 
00107 
00108 /**************************************************************************/
00116 EMSTATUS PAL_SpiTransmit (uint8_t* data, unsigned int len)
00117 {
00118   EMSTATUS status = PAL_EMSTATUS_OK;
00119 
00120   while (len>0)
00121   {
00122     /* Send only one byte if len==1 or data pointer is not aligned at a 16 bit
00123        word location in memory. */
00124     if ((len == 1) || ((unsigned int)data & 0x1))
00125     {
00126       USART_Tx( PAL_SPI_USART_UNIT, *(uint8_t*)data );
00127       len  --;
00128       data ++;
00129     }
00130     else
00131     {
00132       USART_TxDouble( PAL_SPI_USART_UNIT, *(uint16_t*)data );
00133       len  -= 2;
00134       data += 2;
00135     }
00136   }
00137 
00138   /* Wait for transfer to finish */
00139   while (!(PAL_SPI_USART_UNIT->STATUS & USART_STATUS_TXC)) ;
00140 
00141   return status;
00142 }
00143 
00144 
00145 /**************************************************************************/
00153 EMSTATUS PAL_TimerInit (void)
00154 {
00155   EMSTATUS status = PAL_EMSTATUS_OK;
00156 
00157   UDELAY_Calibrate();
00158 
00159   return status;
00160 }
00161 
00162 
00163 /**************************************************************************/
00171 EMSTATUS PAL_TimerShutdown (void)
00172 {
00173   EMSTATUS status = PAL_EMSTATUS_OK;
00174 
00175   /* Nothing to do since the UDELAY_Delay does not use any resources after
00176      the UDELAY_Calibrate has been called. The UDELAY_Calibrate uses the
00177      RTC to calibrate the delay loop, and restores the RTC after use. */
00178 
00179   return status;
00180 }
00181 
00182 
00183 /**************************************************************************/
00190 EMSTATUS PAL_TimerMicroSecondsDelay(unsigned int usecs)
00191 {
00192   EMSTATUS status = PAL_EMSTATUS_OK;
00193 
00194   UDELAY_Delay(usecs);
00195 
00196   return status;
00197 }
00198 
00199 
00200 #ifdef PAL_TIMER_REPEAT_FUNCTION
00201 /**************************************************************************/
00211 EMSTATUS PAL_TimerRepeat (void(*pFunction)(void*),
00212                             void* argument,
00213                             unsigned int frequency)
00214 {
00215   if (0 != PAL_TIMER_REPEAT_FUNCTION(pFunction, argument, frequency))
00216     return PAL_EMSTATUS_REPEAT_FAILED;
00217   else
00218     return EMSTATUS_OK;
00219 }
00220 #endif
00221 
00222 
00223 /**************************************************************************/
00231 EMSTATUS PAL_GpioInit (void)
00232 {
00233   EMSTATUS status = PAL_EMSTATUS_OK;
00234 
00235   /* Enable the GPIO clock in order to access the GPIO module. */
00236   CMU_ClockEnable( cmuClock_GPIO, true );
00237 
00238   return status;
00239 }
00240 
00241 
00242 /**************************************************************************/
00250 EMSTATUS PAL_GpioShutdown (void)
00251 {
00252   EMSTATUS status = PAL_EMSTATUS_OK;
00253 
00254   /* Enable the GPIO clock in order to access the GPIO module. */
00255   CMU_ClockEnable( cmuClock_GPIO, false );
00256 
00257   return status;
00258 }
00259 
00260 
00261 /***************************************************************************/
00280 EMSTATUS PAL_GpioPinModeSet(unsigned int   port,
00281                             unsigned int   pin,
00282                             PAL_GpioMode_t mode,
00283                             unsigned int   platformSpecific)
00284 {
00285   EMSTATUS status = PAL_EMSTATUS_OK;
00286   GPIO_Mode_TypeDef   emGpioMode;
00287 
00288   /* Convert PAL pin mode to GPIO_Mode_TypeDef defined in em_gpio.h.  */
00289   switch (mode)
00290   {
00291   case palGpioModePushPull:
00292     emGpioMode = gpioModePushPull;
00293     break;
00294   default:
00295     return PAL_EMSTATUS_INVALID_PARAM;
00296   }
00297 
00298   GPIO_PinModeSet((GPIO_Port_TypeDef) port, pin, emGpioMode, platformSpecific);
00299 
00300   return status;
00301 }
00302 
00303 
00304 /***************************************************************************/
00319 EMSTATUS PAL_GpioPinOutSet(unsigned int port, unsigned int pin)
00320 {
00321   EMSTATUS status = PAL_EMSTATUS_OK;
00322 
00323   GPIO_PinOutSet((GPIO_Port_TypeDef) port, pin);
00324 
00325   return status;
00326 }
00327 
00328 
00329 /***************************************************************************/
00344 EMSTATUS PAL_GpioPinOutClear(unsigned int port, unsigned int pin)
00345 {
00346   EMSTATUS status = PAL_EMSTATUS_OK;
00347 
00348   GPIO_PinOutClear((GPIO_Port_TypeDef) port, pin);
00349 
00350   return status;
00351 }
00352 
00353 
00354 /***************************************************************************/
00369 EMSTATUS PAL_GpioPinOutToggle(unsigned int port, unsigned int pin)
00370 {
00371   EMSTATUS status = PAL_EMSTATUS_OK;
00372 
00373   GPIO_PinOutToggle((GPIO_Port_TypeDef) port, pin);
00374 
00375   return status;
00376 }
00377 
00378 
00379 #ifdef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE
00380 /**************************************************************************/
00388 EMSTATUS PAL_GpioPinAutoToggle (unsigned int gpioPort,
00389                                 unsigned int gpioPin,
00390                                 unsigned int frequency)
00391 {
00392   EMSTATUS status = EMSTATUS_OK;
00393 
00394 #ifdef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY
00395 
00396   /* We only support auto HW toggling on GPIO port E pin 10 on ZeroSTK.  */
00397   if ( (gpioPortE != gpioPort) || (10 != gpioPin) )
00398   {
00399     status = PAL_EMSTATUS_INVALID_PARAM;
00400   }
00401   else
00402   {
00403     /* Setup PRS to drive the GPIO port E pin 10 which is connected to the
00404        display com inversion pin (EXTCOMIN) using the RTC COMP0 signal as
00405        source. */
00406     unsigned int channel = 2;
00407     uint32_t     source  = PRS_CH_CTRL_SOURCESEL_RTC;
00408     uint32_t     signal  = PRS_CH_CTRL_SIGSEL_RTCCOMP0; 
00409 
00410     /* Enable PRS clock */
00411     CMU_ClockEnable(cmuClock_PRS, true);
00412 
00413     /* Set up PRS to trigger from an RTC compare match */
00414     PRS_SourceAsyncSignalSet(channel, source, signal);
00415 
00416     /* This outputs the PRS pulse on PE10 which is the EXTCOMIN pin */
00417     PRS->ROUTE = (PRS_ROUTE_CH2PEN | PRS_ROUTE_LOCATION_LOC2);
00418   }
00419 #else
00420   /* Store GPIO pin data. */
00421   gpioPortNo = gpioPort;
00422   gpioPinNo  = gpioPin;
00423 #endif
00424 
00425   if (EMSTATUS_OK == status)
00426   {
00427     /* Setup GPIO pin. */
00428     GPIO_PinModeSet((GPIO_Port_TypeDef)gpioPort, gpioPin, gpioModePushPull, 0 );
00429 
00430     /* Setup RTC to to toggle PRS or generate interrupts at given frequency. */
00431     rtcSetup(frequency);
00432   }
00433 
00434   return status;
00435 }
00436 
00437 
00438 #ifdef  INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE
00439 #ifndef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY
00440 /**************************************************************************/
00445 void RTC_IRQHandler(void)
00446 {
00447   /* Clear interrupt source */
00448   RTC_IntClear(RTC_IF_COMP0);
00449 
00450   /* Toggle GPIO pin. */
00451   GPIO_PinOutToggle((GPIO_Port_TypeDef)gpioPortNo, gpioPinNo );
00452 }
00453 #endif
00454 #endif
00455 
00456 
00457 /**************************************************************************/
00461 static void rtcSetup(unsigned int frequency)
00462 {
00463   RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT;
00464 
00465   /* Enable LE domain registers */
00466   if ( !( CMU->HFCORECLKEN0 & CMU_HFCORECLKEN0_LE) )
00467   {
00468     CMU_ClockEnable(cmuClock_CORELE, true);
00469   }
00470 
00471 #ifdef PAL_RTC_CLOCK_LFXO
00472   /* LFA with LFXO setup is relatively time consuming. Therefore, check if it
00473      already enabled before calling. */
00474   if ( !(CMU->STATUS & CMU_STATUS_LFXOENS) )
00475   {
00476     CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
00477   }
00478   if ( cmuSelect_LFXO != CMU_ClockSelectGet(cmuClock_LFA) )
00479   {
00480     CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO);
00481   }
00482 #elif defined PAL_RTC_CLOCK_LFRCO
00483   /* Enable LFACLK in CMU (will also enable LFRCO oscillator if not enabled) */
00484   CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO);
00485 #elif defined PAL_RTC_CLOCK_ULFRCO
00486   /* Enable LFACLK in CMU (will also enable ULFRCO oscillator if not enabled) */
00487   CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_ULFRCO);
00488 #else
00489 #error No clock source for RTC defined.
00490 #endif
00491 
00492   /* Set the prescaler. */
00493   CMU_ClockDivSet( cmuClock_RTC, cmuClkDiv_2 );
00494 
00495   /* Enable RTC clock */
00496   CMU_ClockEnable(cmuClock_RTC, true);
00497 
00498   /* Initialize RTC */
00499   rtcInit.enable   = false;  /* Do not start RTC after initialization is complete. */
00500   rtcInit.debugRun = false;  /* Halt RTC when debugging. */
00501   rtcInit.comp0Top = true;   /* Wrap around on COMP0 match. */
00502   RTC_Init(&rtcInit);
00503 
00504   /* Interrupt at given frequency. */
00505   RTC_CompareSet(0, (CMU_ClockFreqGet(cmuClock_RTC) / frequency) - 1 );
00506 
00507 #ifndef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY
00508   /* Enable interrupt */
00509   NVIC_EnableIRQ(RTC_IRQn);
00510   RTC_IntEnable(RTC_IEN_COMP0);
00511 #endif
00512 
00513   /* Start Counter */
00514   RTC_Enable(true);
00515 }
00516 #endif  /* INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE */
00517