main: add NEC code transmission

This commit is contained in:
King Kévin 2022-10-12 17:37:00 +02:00
parent 536ca1f755
commit e813e6bf46
1 changed files with 76 additions and 17 deletions

93
main.c
View File

@ -174,6 +174,82 @@ static void timer_ir_in(void)
IRM_ON_PORT->ODR.reg |= IRM_ON_PIN; // switch IR demodulator on
}
#define TIM1_PERIOD 421U // 16E6/(0+1)/38000
// configure timer to transmit IR burst at 38 kHz
static void timer_ir_out(void)
{
IRM_ON_PORT->ODR.reg &= ~IRM_ON_PIN; // switch IR demodulator off
TIM1->CR1.reg = 0; // disable counter before reconfiguring it
TIM1->CCER1.reg = 0; // reset register
TIM1->CCER2.reg = 0; // reset register
TIM1->IER.reg = 0; // reset interrupts
TIM1->PSCRH.reg = 0; // set prescaler to get most precise 38 kHz
TIM1->PSCRL.reg = 0; // 16E6/(0+1)/65536 = down to 244 Hz
TIM1->ARRH.reg = (TIM1_PERIOD >> 8); // set auto-reload register for 38 kHz period
TIM1->ARRL.reg = (TIM1_PERIOD & 0xff); // 16E6/(0+1)/38000
TIM1->CCR4H.reg = (TIM1_PERIOD / 3) >> 8; // set duty cycle to 33%
TIM1->CCR4L.reg = (TIM1_PERIOD / 3 ) & 0xff; // set duty cycle to 33%
TIM1->CCMR4.output_fields.OC4M = 6; // set PWM1 mode
TIM1->CCMR4.output_fields.CC4S = 0; // use channel as output
TIM1->CCER2.fields.CC4E = 1; // enable channel output
TIM1->BKR.fields.MOE = 1; // enable outputs
TIM1->SR1.reg = 0; // clear all flags
TIM1->CNTRL.reg = 0; // reset counter
TIM1->CNTRH.reg = 0; // reset counter
TIM1->CR1.fields.OPM = 1; // send one pulse at a time
TIM1->EGR.fields.UG = 1; // transfer all registers
// don't enable timer yet
}
// transmit IR pulses
static void nec_pulse(uint16_t pulses, bool mark)
{
if (mark) {
TIM1->CCR4H.reg = (TIM1_PERIOD / 3) >> 8; // set duty cycle to 33%
TIM1->CCR4L.reg = (TIM1_PERIOD / 3 ) & 0xff; // set duty cycle to 33%
} else {
TIM1->CCR4H.reg = 0; // set duty cycle to 0%
TIM1->CCR4L.reg = 0; // set duty cycle to 0%
}
while (pulses--) {
TIM1->CR1.fields.CEN = 1; // enable counter to start PWM for 1 pulse
while (TIM1->CR1.fields.CEN); // wait until pulse completes
}
// ensure we are off at the end
TIM1->CCR4H.reg = 0; // set duty cycle to 0%
TIM1->CCR4L.reg = 0; // set duty cycle to 0%
}
// transmit 4 byte NEC code over IR (LSb first)
static void nec_transmit(uint32_t code)
{
if (NULL == code) {
return;
}
timer_ir_out(); // configure to transmit pulses
sim(); // disable interrupts to keep timings tight
// all time are hand tuned
nec_pulse(333, true); // send AGC burst, 9 ms
nec_pulse(166, false); // AGC space, 4.5 ms
// transmit bits
for (uint8_t i = 0; i < 32; i++) {
nec_pulse(21, true); // bit burst, 560 us
if (code & 0x1) {
nec_pulse(61, false); // bit space, 2.25 ms - 560 us
} else {
nec_pulse(21, false); // bit space, 1.12 ms - 560 us
}
code >>= 1; // go to next bit
}
nec_pulse(22, true); // end pulse, 560 us
rim(); // re-enable interrupts
timer_ir_in(); // go back to IR capture
}
void main(void)
{
sim(); // disable interrupts (while we reconfigure them)
@ -265,23 +341,6 @@ void main(void)
TIM4->CR1.fields.URS = 1; // only update on overflow
TIM4->CR1.fields.CEN = 1; // enable counter
/*
// configure timer to modulate IR LEDs at 38 kHz
TIM1->PSCRH.reg = 0; // set prescaler to get most precise 38 kHz
TIM1->PSCRL.reg = 0; // 16E6/(0+1)/65536 = down to 244 Hz
#define TIM1_PERIOD 421U // 16E6/(0+1)/38000
TIM1->ARRH.reg = (TIM1_PERIOD >> 8); // set auto-reload register for 38 kHz period
TIM1->ARRL.reg = (TIM1_PERIOD & 0xff); // 16E6/(0+1)/38000
TIM1->CCR4H.reg = (TIM1_PERIOD / 3) >> 8; // set duty cycle to 33%
TIM1->CCR4L.reg = (TIM1_PERIOD / 3 ) & 0xff; // set duty cycle to 33%
TIM1->CCMR4.output_fields.OC4M = 6; // set PWM1 mode
TIM1->CCMR4.output_fields.CC4S = 0; // use channel as output
TIM1->CCER2.fields.CC4E = 1; // enable channel output
TIM1->BKR.fields.MOE = 1; // enable outputs
TIM1->EGR.fields.UG = 1; // transfer all registers
TIM1->CR1.fields.CEN = 1; // enable counter to start PWM
*/
// configure timer to receive IR message
timer_ir_in();