Skip to content

Instantly share code, notes, and snippets.

@vk2tds
Last active October 14, 2015 06:04
Show Gist options
  • Save vk2tds/c6048fd65b4e82087396 to your computer and use it in GitHub Desktop.
Save vk2tds/c6048fd65b4e82087396 to your computer and use it in GitHub Desktop.
This is a snippet of code that allows IR to be sent using PWM on the Spark Core.
void setup() {
}
void loop(){
unsigned int ir[] = {8576,4224,640,1664,640,640,640,640,640,640,640,1664,640,640,640,640,640,640,640,640,640,640,
640,640,640,640,640,640,640,1664,640,640,640,640,640,1664,640,640,640,640,640,640,640,640,
640,640,640,640,640,640,640,1664,640,1664,640,640,640,640,640};
send (ir, 59, 36000);
}
// From https://github.com/zoellner/IRLib/blob/master/IRLib.cpp and also
// based on https://gist.github.com/technobly/8313449
uint16_t TIM_ARR = (uint16_t)(24000000 / 38000) - 1; // 38 KHz Init
// User defined analogWrite() to gain control of PWM initialization
void analogWrite2(uint16_t pin, uint8_t value) {
TIM_OCInitTypeDef TIM_OCInitStructure;
if (pin >= TOTAL_PINS || PIN_MAP[pin].timer_peripheral == NULL) {
return;
}
// SPI safety check
if (SPI.isEnabled() == true && (pin == SCK || pin == MOSI || pin == MISO)) {
return;
}
// I2C safety check
if (Wire.isEnabled() == true && (pin == SCL || pin == SDA)) {
return;
}
// Serial1 safety check
if (Serial1.isEnabled() == true && (pin == RX || pin == TX)) {
return;
}
if (PIN_MAP[pin].pin_mode != OUTPUT && PIN_MAP[pin].pin_mode != AF_OUTPUT_PUSHPULL) {
return;
}
// Don't re-init PWM and cause a glitch if already setup, just update duty cycle and return.
if (PIN_MAP[pin].pin_mode == AF_OUTPUT_PUSHPULL) {
TIM_OCInitStructure.TIM_Pulse = (uint16_t)(value * (TIM_ARR + 1) / 255);
if (PIN_MAP[pin].timer_ch == TIM_Channel_1) {
PIN_MAP[pin].timer_peripheral-> CCR1 = TIM_OCInitStructure.TIM_Pulse;
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_2) {
PIN_MAP[pin].timer_peripheral-> CCR2 = TIM_OCInitStructure.TIM_Pulse;
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_3) {
PIN_MAP[pin].timer_peripheral-> CCR3 = TIM_OCInitStructure.TIM_Pulse;
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_4) {
PIN_MAP[pin].timer_peripheral-> CCR4 = TIM_OCInitStructure.TIM_Pulse;
}
return;
}
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//PWM Frequency : PWM_FREQ (Hz)
uint16_t TIM_Prescaler = (uint16_t)(SystemCoreClock / 24000000) - 1; //TIM Counter clock = 24MHz
// TIM Channel Duty Cycle(%) = (TIM_CCR / TIM_ARR + 1) * 100
uint16_t TIM_CCR = (uint16_t)(value * (TIM_ARR + 1) / 255);
// AFIO clock enable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//pinMode(pin, AF_OUTPUT_PUSHPULL); // we need to do this manually else we get a glitch
// TIM clock enable
if (PIN_MAP[pin].timer_peripheral == TIM2)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
else if (PIN_MAP[pin].timer_peripheral == TIM3)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
else if (PIN_MAP[pin].timer_peripheral == TIM4)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
// Time base configuration
TIM_TimeBaseStructure.TIM_Period = TIM_ARR;
TIM_TimeBaseStructure.TIM_Prescaler = TIM_Prescaler;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(PIN_MAP[pin].timer_peripheral, & TIM_TimeBaseStructure);
// PWM1 Mode configuration
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = TIM_CCR;
if (PIN_MAP[pin].timer_ch == TIM_Channel_1) {
// PWM1 Mode configuration: Channel1
TIM_OC1Init(PIN_MAP[pin].timer_peripheral, & TIM_OCInitStructure);
TIM_OC1PreloadConfig(PIN_MAP[pin].timer_peripheral, TIM_OCPreload_Enable);
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_2) {
// PWM1 Mode configuration: Channel2
TIM_OC2Init(PIN_MAP[pin].timer_peripheral, & TIM_OCInitStructure);
TIM_OC2PreloadConfig(PIN_MAP[pin].timer_peripheral, TIM_OCPreload_Enable);
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_3) {
// PWM1 Mode configuration: Channel3
TIM_OC3Init(PIN_MAP[pin].timer_peripheral, & TIM_OCInitStructure);
TIM_OC3PreloadConfig(PIN_MAP[pin].timer_peripheral, TIM_OCPreload_Enable);
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_4) {
// PWM1 Mode configuration: Channel4
TIM_OC4Init(PIN_MAP[pin].timer_peripheral, & TIM_OCInitStructure);
TIM_OC4PreloadConfig(PIN_MAP[pin].timer_peripheral, TIM_OCPreload_Enable);
}
TIM_ARRPreloadConfig(PIN_MAP[pin].timer_peripheral, ENABLE);
// TIM enable counter
TIM_Cmd(PIN_MAP[pin].timer_peripheral, ENABLE);
}
void enableIROut (unsigned int hz){
pinMode (A5, OUTPUT);
TIM_ARR = (uint16_t)(24000000 / hz) - 1;
analogWrite2 (A5,128); // 50% Duty Cycle
pinMode(A5, AF_OUTPUT_PUSHPULL);
space(0); // And turn off the PWM output until we need it
delay(100);
}
void My_delay_uSecs(unsigned int T) {
if(T){if(T>16000) {delayMicroseconds(T % 1000); delay(T/1000); } else delayMicroseconds(T);};
}
void mark(unsigned int time) {
//pinMode(A5, AF_OUTPUT_PUSHPULL);
analogWrite2 (A5,128);
My_delay_uSecs(time);
}
void space(unsigned int time) {
//pinMode(A5, OUTPUT);
analogWrite2 (A5,0);
My_delay_uSecs(time);
}
void send(unsigned short buf[], unsigned char len, unsigned int hz)
{
if (hz == 0){
enableIROut(38000);
} else {
enableIROut(hz);
}
for (unsigned char i = 0; i < len; i++) {
if (i & 1) {
space(buf[i]);
}
else {
mark(buf[i]);
}
}
space(0); // Just to be sure
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment