+ CDC
+ Fast PWM
- Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
+ Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
This file is part of simavr.
break;
}
- return p->tov_cycles ? 0 : p->comp[comp].comp_cycles ? when
- + p->comp[comp].comp_cycles : 0;
+ return p->tov_cycles ? 0 :
+ p->comp[comp].comp_cycles ?
+ when + p->comp[comp].comp_cycles : 0;
}
static avr_cycle_count_t avr_timer_compa(struct avr_t * avr, avr_cycle_count_t when, void * param)
// this involves some magicking
// cancel the current timers, recalculate the "base" we should be at, reset the
- // timer base as it should, and re-shedule the timers using that base.
+ // timer base as it should, and re-schedule the timers using that base.
avr_cycle_timer_cancel(avr, avr_timer_tov, p);
avr_cycle_timer_cancel(avr, avr_timer_compa, p);
p->tov_top = top;
p->tov_cycles = frequency / t; // avr_hz_to_cycles(frequency, t);
- printf("%s-%c TOP %.2fHz = %d cycles\n", __FUNCTION__, p->name, t, (int)p->tov_cycles);
+
+ AVR_LOG(p->io.avr, LOG_TRACE, "TIMER: %s-%c TOP %.2fHz = %d cycles\n",
+ __FUNCTION__, p->name, t, (int)p->tov_cycles);
for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
+ if (!p->comp[compi].r_ocr)
+ continue;
uint32_t ocr = _timer_get_ocr(p, compi);
float fc = clock / (float)(ocr+1);
p->comp[compi].comp_cycles = 0;
-// printf("%s-%c clock %d top %d OCR%c %d\n", __FUNCTION__, p->name, clock, top, 'A'+compi, ocr);
+ // printf("%s-%c clock %d top %d OCR%c %d\n", __FUNCTION__, p->name, clock, top, 'A'+compi, ocr);
if (ocr && ocr <= top) {
p->comp[compi].comp_cycles = frequency / fc; // avr_hz_to_cycles(p->io.avr, fa);
- printf("%s-%c %c %.2fHz = %d cycles\n", __FUNCTION__, p->name,
+ AVR_LOG(p->io.avr, LOG_TRACE, "TIMER: %s-%c %c %.2fHz = %d cycles\n", __FUNCTION__, p->name,
'A'+compi, fc, (int)p->comp[compi].comp_cycles);
}
}
uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
if (cs == 0) {
- printf("%s-%c clock turned off\n", __FUNCTION__, p->name);
+ AVR_LOG(avr, LOG_TRACE, "TIMER: %s-%c clock turned off\n", __FUNCTION__, p->name);
return;
}
case avr_timer_wgm_normal:
avr_timer_configure(p, f, (1 << p->mode.size) - 1);
break;
+ case avr_timer_wgm_fc_pwm:
+ avr_timer_configure(p, f, (1 << p->mode.size) - 1);
+ break;
case avr_timer_wgm_ctc: {
avr_timer_configure(p, f, _timer_get_ocr(p, AVR_TIMER_COMPA));
} break;
avr_timer_configure(p, f, (1 << p->mode.size) - 1);
break;
default:
- printf("%s-%c unsupported timer mode wgm=%d (%d)\n", __FUNCTION__, p->name, mode, p->mode.kind);
+ AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c unsupported timer mode wgm=%d (%d)\n",
+ __FUNCTION__, p->name, mode, p->mode.kind);
}
}
static void avr_timer_write_ocr(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
avr_timer_t * p = (avr_timer_t *)param;
+ uint16_t oldv[AVR_TIMER_COMP_COUNT];
+ int target = -1;
+
+ /* check to see if the OCR values actually changed */
+ for (int oi = 0; oi < AVR_TIMER_COMP_COUNT; oi++)
+ oldv[oi] = _timer_get_ocr(p, oi);
avr_core_watch_write(avr, addr, v);
+ for (int oi = 0; oi < AVR_TIMER_COMP_COUNT; oi++)
+ if (oldv[oi] != _timer_get_ocr(p, oi)) {
+ target = oi;
+ break;
+ }
switch (p->mode.kind) {
case avr_timer_wgm_normal:
avr_timer_reconfigure(p);
break;
+ case avr_timer_wgm_fc_pwm: // OCR is not used here
+ avr_timer_reconfigure(p);
+ break;
+ case avr_timer_wgm_ctc:
+ avr_timer_reconfigure(p);
+ break;
case avr_timer_wgm_pwm:
if (p->mode.top != avr_timer_wgm_reg_ocra) {
avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(p, AVR_TIMER_COMPA));
}
break;
case avr_timer_wgm_fast_pwm:
+ if (target != -1)
+ avr_timer_reconfigure(p);
avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(p, AVR_TIMER_COMPA));
avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(p, AVR_TIMER_COMPB));
break;
default:
- printf("%s-%c mode %d UNSUPPORTED\n", __FUNCTION__, p->name, p->mode.kind);
+ AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c mode %d UNSUPPORTED\n", __FUNCTION__, p->name, p->mode.kind);
avr_timer_reconfigure(p);
break;
}