Last active
July 12, 2016 21:26
-
-
Save monpetit/bfb53385cd64bff31cc717d4dfc06201 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <inttypes.h> | |
#include "em_device.h" | |
#include "em_chip.h" | |
#include "em_cmu.h" | |
#include "em_emu.h" | |
#include "em_int.h" | |
#include "em_timer.h" | |
#define LED_PIN (0) | |
#define LED_PORT (gpioPortA) | |
volatile uint32_t systick_count = 0; | |
uint32_t clock_freq; | |
__STATIC_INLINE void __delay_tick(volatile uint32_t n); | |
__STATIC_INLINE uint32_t get_systick(void); | |
void __delay_ms(uint32_t milliseconds); | |
void setup_systick_timer(void); | |
void reset_blink(volatile uint8_t countdown); | |
void init_clocks(void); | |
void init_timer0(void); | |
void init_portio(void); | |
/* Define PWM frequency value */ | |
#define PWM_FREQ 20000 | |
uint32_t timer0_top; | |
void pulse_out(unsigned int ch, uint32_t duty_cycle) | |
{ | |
if (duty_cycle <= 100) | |
TIMER_CompareBufSet(TIMER0, ch, (duty_cycle * timer0_top) / 100); | |
} | |
/**************************************************************************//** | |
* @brief Main function | |
*****************************************************************************/ | |
int main(void) | |
{ | |
/* Chip errata */ | |
CHIP_Init(); | |
/* Enter default mode */ | |
init_clocks(); | |
init_portio(); | |
init_timer0(); | |
/* Ensure core frequency has been updated */ | |
SystemCoreClockUpdate(); | |
/* Start Systick Timer */ | |
setup_systick_timer(); | |
/* Set Top Value */ | |
uint32_t freq = CMU_ClockFreqGet(cmuClock_HFPER); | |
timer0_top = freq / PWM_FREQ; | |
TIMER_TopSet(TIMER0, timer0_top); | |
reset_blink(30); | |
/* Infinite loop */ | |
while (1) { | |
for (uint32_t i = 0; i <= 100; i++) { | |
pulse_out(0, i); | |
pulse_out(2, 100 - i); | |
__delay_ms(15); | |
} | |
} | |
} | |
void SysTick_Handler(void) | |
{ | |
systick_count++; | |
} | |
__STATIC_INLINE uint32_t get_systick(void) | |
{ | |
return systick_count; | |
} | |
/****************************************************************************** | |
* @brief Delay function | |
*****************************************************************************/ | |
void __delay_ms(uint32_t milliseconds) | |
{ | |
uint32_t start_tick = get_systick(); | |
while ((get_systick() - start_tick) < milliseconds) { | |
} | |
} | |
void setup_systick_timer(void) | |
{ | |
clock_freq = CMU_ClockFreqGet(cmuClock_CORE); | |
/* Enable SysTick interrupt, necessary for __delay_ms() */ | |
if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ; | |
NVIC_EnableIRQ(SysTick_IRQn); | |
} | |
void reset_blink(volatile uint8_t countdown) | |
{ | |
volatile uint8_t cnt = countdown / 2; | |
while (cnt--) { | |
pulse_out(0, 100); | |
__delay_ms(20); | |
pulse_out(0, 0); | |
__delay_ms(20); | |
} | |
__delay_ms(1000); | |
} | |
void init_clocks(void) | |
{ | |
// $[HFXO] | |
CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOMODE_MASK) | CMU_CTRL_HFXOMODE_XTAL; | |
CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBOOST_MASK) | |
| CMU_CTRL_HFXOBOOST_50PCENT; | |
SystemHFXOClockSet(32000000); | |
// $[Use oscillator source] | |
CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_LFXOMODE_MASK) | CMU_CTRL_LFXOMODE_XTAL; | |
// [Use oscillator source]$ | |
// $[LFXO Boost Percent] | |
CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_LFXOBOOST_MASK) | |
| CMU_CTRL_LFXOBOOST_100PCENT; | |
// [LFXO Boost Percent]$ | |
// $[LFXO enable] | |
CMU_OscillatorEnable(cmuOsc_LFXO, true, true); | |
// [LFXO enable]$ | |
// $[HFXO enable] | |
CMU_OscillatorEnable(cmuOsc_HFXO, true, true); | |
// [HFXO enable]$ | |
// $[High Frequency Clock select] | |
/* Using HFXO as high frequency clock, HFCLK */ | |
CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); | |
/* Enable peripheral clock */ | |
CMU_ClockEnable(cmuClock_HFPER, true); | |
// [High Frequency Clock select]$ | |
// $[Peripheral Clock enables] | |
/* Enable clock for TIMER0 */ | |
CMU_ClockEnable(cmuClock_TIMER0, true); | |
/* Enable clock for GPIO by default */ | |
CMU_ClockEnable(cmuClock_GPIO, true); | |
// [Peripheral Clock enables]$ | |
} | |
void init_portio(void) | |
{ | |
// $[Port A Configuration] | |
/* Pin PA0 is configured to Push-pull */ | |
GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | |
| GPIO_P_MODEL_MODE0_PUSHPULL; | |
/* Pin PA2 is configured to Push-pull */ | |
GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE2_MASK) | |
| GPIO_P_MODEL_MODE2_PUSHPULL; | |
// [Port A Configuration]$ | |
// $[Route Configuration] | |
/* Enable signals CC0, CC2 */ | |
TIMER0->ROUTE |= TIMER_ROUTE_CC0PEN | TIMER_ROUTE_CC2PEN; | |
// [Route Configuration]$ | |
} | |
void init_timer0(void) | |
{ | |
// $[TIMER0 initialization] | |
TIMER_Init_TypeDef init = TIMER_INIT_DEFAULT; | |
init.enable = 1; | |
init.debugRun = 1; | |
init.dmaClrAct = 0; | |
init.sync = 0; | |
init.clkSel = timerClkSelHFPerClk; | |
init.prescale = timerPrescale64; | |
init.fallAction = timerInputActionNone; | |
init.riseAction = timerInputActionNone; | |
init.mode = timerModeUp; | |
init.quadModeX4 = 0; | |
init.oneShot = 0; | |
TIMER_Init(TIMER0, &init); | |
// [TIMER0 initialization]$ | |
// $[TIMER0 CC0 init] | |
TIMER_InitCC_TypeDef initCC0 = TIMER_INITCC_DEFAULT; | |
initCC0.prsInput = false; | |
initCC0.prsSel = timerPRSSELCh0; | |
initCC0.edge = timerEdgeBoth; | |
initCC0.mode = timerCCModePWM; | |
initCC0.eventCtrl = timerEventEveryEdge; | |
initCC0.filter = 0; | |
initCC0.cofoa = timerOutputActionNone; | |
initCC0.cufoa = timerOutputActionNone; | |
initCC0.cmoa = timerOutputActionToggle; | |
initCC0.coist = 0; | |
initCC0.outInvert = 0; | |
TIMER_InitCC(TIMER0, 0, &initCC0); | |
// [TIMER0 CC0 init]$ | |
// $[TIMER0 CC2 init] | |
TIMER_InitCC_TypeDef initCC2 = TIMER_INITCC_DEFAULT; | |
initCC2.prsInput = false; | |
initCC2.prsSel = timerPRSSELCh0; | |
initCC2.edge = timerEdgeBoth; | |
initCC2.mode = timerCCModePWM; | |
initCC2.eventCtrl = timerEventEveryEdge; | |
initCC2.filter = 0; | |
initCC2.cofoa = timerOutputActionNone; | |
initCC2.cufoa = timerOutputActionNone; | |
initCC2.cmoa = timerOutputActionToggle; | |
initCC2.coist = 0; | |
initCC2.outInvert = 0; | |
TIMER_InitCC(TIMER0, 2, &initCC2); | |
// [TIMER0 CC2 init]$ | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment