Sólo un boceto rápido:
#define F_TIMER_TICK 300 // in Hz
#define PHASE_NORMAL 0
#define PHASE_INVERSE 1
typedef struct pwmDef {
uint8_t ticksOnPerCylce;
uint8_t ticksPerCycle;
uint8_t phase;
} pwmDef_t;
typedef struct doublePwmDef {
pwmDef_t pin9;
pwmDef_t pin10;
} doublePwmDef_t;
const doublePwmDef_t T0 = {
{
(uint8_t) (F_TIMER_TICK / (2 / 0.5)),
(uint8_t) ( F_TIMER_TICK / 2 ),
PHASE_NORMAL
},
{
(uint8_t) ( F_TIMER_TICK / (2 / 0.5) ),
(uint8_t) ( F_TIMER_TICK / 2 ),
PHASE_NORMAL
}
};
const doublePwmDef_t T1 = {
{
(uint8_t) ( F_TIMER_TICK / (3 / 0.5) ),
(uint8_t) ( F_TIMER_TICK / 3 ),
PHASE_NORMAL
},
{
(uint8_t) ( F_TIMER_TICK / (15 / 0.2) ),
(uint8_t) ( F_TIMER_TICK / 15 ),
PHASE_NORMAL
}
};
const doublePwmDef_t T2 = {
...
};
const doublePwmDef_t T3 = {
{
(uint8_t) (F_TIMER_TICK / (2 / 0.5)),
(uint8_t) ( F_TIMER_TICK / 2 ),
PHASE_NORMAL
},
{
(uint8_t) ( F_TIMER_TICK / (2 / 0.5) ),
(uint8_t) ( F_TIMER_TICK / 2 ),
PHASE_INVERSE
}
};
// etc.
const doublePwmDef_t[] PWM_DEFS = {
T0,
T1,
T2,
T3
}
// etc.
volatile uint8_t mode;
volatile uint8_t tickCount9;
volatile uint8_t tickCount10;
ISR(TIMER0_COMPA_vect) {
OCR0A += <trigger again in 1/300s>;
const doublePwmDef_t currentPwmDef = PWM_DEFS[ mode ];
if ( tickCount9 >= currentPwmDef.pin9.ticksPerCycle ) {
tickCount9 = 0;
}
if (tickCount9 < currentPwmDef.pin9.ticksOnPerCylce) {
if ( currentPwmDef.pin9.phase == PHASE_NORMAL ) {
// Turn pin 9 ON
} else {
// Turn pin 9 OFF
}
} else {
if ( currentPwmDef.pin9.phase == PHASE_NORMAL ) {
// Turn pin 9 OFF
} else {
// Turn pin 9 ON
}
}
tickCount9++;
// Repeat the above for pin 10...
}
void switchMode( uint8_t newMode ) {
cli();
mode = newMode;
tickCount9 = 0;
tickCount10 = 0;
sei();
}
Si usa los pines de E / S correctos (por ejemplo, OC1A y OC1B), podría aprovechar el PWM de hardware, que no he considerado aquí; en ese caso, podría evitar escribir un ISR.