I changed the code slightly to make it easier and more consistent.
//generate multiple ppm output
//pin configuration
#define PWM_PORT PORTB
#define PWM_DDR DDRB
#define PWM0 (1<<0)
#define PWM1 (1<<1)
#define PWM2 (1<<2)
#define PWM3 (1<<3)
#define PWM4 (1<<4)
#define PWM5 (1<<5)
//set pwm duration for each bit
#define PWM_Bit (PWM_100us) //duration of 1 bit
//pin configuration
//defining timing constants
#define PWM_ms (F_CPU / 64 / 1000) //milli seconds, 64:1 prescaler
#define PWM_1ms (PWM_ms)
#define PWM_500us (PWM_1ms / 2)
#define PWM_250us (PWM_500us / 2)
#define PWM_100us (PWM_500us / 5)
#define PWM_2ms (PWM_1ms * 2)
#define PWM_5ms (PWM_1ms * 5)
#define PWM_10ms (PWM_1ms * 10)
//duration examples for 6 channels
unsigned char duration[]={
1, //expected output: 1 / 31 * 5v
4, //expected output: 4 / 31 * 5v
8, //expected output: 8 / 31 * 5v
16, //expected output: 16 / 31 * 5v
30, //expected output: 30 / 31 * 5v
7}; //expected output: 7 / 31 * 5v
//tmr1 ctc isr
ISR(TIMER1_COMPA_vect) {
static unsigned char index = 0; //index
//update the period
if (index) OCR1A = OCR1A * 2;
else OCR1A = PWM_Bit;
//change the pins
if (duration[0] & (1<<index)) PWM_PORT |= PWM0; //set pwm0
else PWM_PORT &=~PWM0; //clear pwm0
if (duration[1] & (1<<index)) PWM_PORT |= PWM1; //set pwm1
else PWM_PORT &=~PWM1; //clear pwm1
if (duration[2] & (1<<index)) PWM_PORT |= PWM2; //set pwm2
else PWM_PORT &=~PWM2; //clear pwm2
if (duration[3] & (1<<index)) PWM_PORT |= PWM3; //set pwm3
else PWM_PORT &=~PWM3; //clear pwm3
if (duration[4] & (1<<index)) PWM_PORT |= PWM4; //set pwm4
else PWM_PORT &=~PWM4; //clear pwm4
if (duration[5] & (1<<index)) PWM_PORT |= PWM5; //set pwm5
else PWM_PORT &=~PWM5; //clear pwm5
//update index
index += 1; // incrment index
if (index == 5) index = 0; //wrap around index
}
//set up the timer1, 64:1 prescaler
void tmr1_init(unsigned short period) {
TCCR1B &=~0x07; //stop tmr1
//set up tccr1a
TCCR1A = (0<<COM1A1) | (0<<COM1A0) | //com1a10 = 0b00, normal operations
(0<<COM1B1) | (0<<COM1B0) | //com1b10 = 0b00, normal operations
(0<<WGM11) | (0<<WGM10); //wgm2..0 = 0b0100, top at OCR1A
TCCR1B = (0<<ICNC1) | (0<<ICES1) | //disable input capture noise canceller and input capture edge select
(0<<WGM13) | (1<<WGM12) | //wgm3..0 = 0b0100, top at OCR1A
(0<<CS12) | (1<<CS11) | (1<<CS10); //cs2..0 = 0b0011, 64:1 prescaler
TCCR1C = 0x00;
//reset the timer/counter
TCNT1 = 0x0000; //reset the timer
//load the period
OCR1A = period;
//reset the flag
TIFR1 |= (1<<OCF1A);
//enable the interrupt
TIMSK1 |= (1<<OCIE1A);
}
void setup(void) {
//initialize the output pins
PWM_PORT |= PWM0 | PWM1 | PWM2 | PWM3 | PWM4 | PWM5; //set the pins
PWM_DDR |= PWM0 | PWM1 | PWM2 | PWM3 | PWM4 | PWM5; //set up the pins for output
//set up the timer
tmr1_init(PWM_Bit);
//enable interrupt
sei();
}
void loop(void) {
}