From: Michel Pollet Date: Thu, 5 Apr 2012 14:26:05 +0000 (+0100) Subject: timer: Added phase correct mode, possibly works X-Git-Url: http://git.rot13.org/?p=simavr;a=commitdiff_plain;h=59c1754a7505a44571a496c39ee2ed8afb40620b timer: Added phase correct mode, possibly works Not tested.. Signed-off-by: Michel Pollet --- diff --git a/simavr/cores/sim_megax4.h b/simavr/cores/sim_megax4.h index ecfd491..21f3130 100644 --- a/simavr/cores/sim_megax4.h +++ b/simavr/cores/sim_megax4.h @@ -276,6 +276,9 @@ struct mcu_t SIM_CORENAME = { AVR_IO_REGBIT(TCCR1B, WGM12), AVR_IO_REGBIT(TCCR1B, WGM13) }, .wgm_op = { [0] = AVR_TIMER_WGM_NORMAL16(), + [1] = AVR_TIMER_WGM_FCPWM8(), + [2] = AVR_TIMER_WGM_FCPWM9(), + [3] = AVR_TIMER_WGM_FCPWM10(), [4] = AVR_TIMER_WGM_CTC(), [5] = AVR_TIMER_WGM_FASTPWM8(), [6] = AVR_TIMER_WGM_FASTPWM9(), diff --git a/simavr/sim/avr_timer.c b/simavr/sim/avr_timer.c index bca6d9d..9c8a3f9 100644 --- a/simavr/sim/avr_timer.c +++ b/simavr/sim/avr_timer.c @@ -190,7 +190,9 @@ static void avr_timer_configure(avr_timer_t * p, uint32_t clock, uint32_t top) 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); + + if (p->trace_flags) + printf("%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) @@ -199,11 +201,12 @@ static void avr_timer_configure(avr_timer_t * p, uint32_t clock, uint32_t top) 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, + if (p->trace_flags & (1 << compi)) + printf("%s-%c %c %.2fHz = %d cycles\n", __FUNCTION__, p->name, 'A'+compi, fc, (int)p->comp[compi].comp_cycles); } } @@ -255,6 +258,9 @@ static void avr_timer_reconfigure(avr_timer_t * p) 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; @@ -266,19 +272,38 @@ static void avr_timer_reconfigure(avr_timer_t * p) 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); + printf("%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; - avr_core_watch_write(avr, addr, v); + uint16_t oldv[AVR_TIMER_COMP_COUNT]; + int target = -1; + /* vheck to see if the OCR values actualy 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; + } + uint16_t otrace = p->trace_flags; + if (target != -1) { + p->trace_flags = 1 << target; + } else { + p->trace_flags = 0; + } 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 + break; case avr_timer_wgm_ctc: avr_timer_reconfigure(p); break; @@ -297,6 +322,7 @@ static void avr_timer_write_ocr(struct avr_t * avr, avr_io_addr_t addr, uint8_t avr_timer_reconfigure(p); break; } + p->trace_flags = otrace; } static void avr_timer_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) @@ -458,4 +484,5 @@ void avr_timer_init(avr_t * avr, avr_timer_t * p) } avr_register_io_write(avr, p->r_tcnt, avr_timer_tcnt_write, p); avr_register_io_read(avr, p->r_tcnt, avr_timer_tcnt_read, p); + p->trace_flags = 0xf; } diff --git a/simavr/sim/avr_timer.h b/simavr/sim/avr_timer.h index a159138..04b25e8 100644 --- a/simavr/sim/avr_timer.h +++ b/simavr/sim/avr_timer.h @@ -50,6 +50,7 @@ enum { avr_timer_wgm_ctc, avr_timer_wgm_pwm, avr_timer_wgm_fast_pwm, + avr_timer_wgm_fc_pwm, }; // Compare output modes @@ -77,6 +78,9 @@ typedef struct avr_timer_wgm_t { #define AVR_TIMER_WGM_FASTPWM8() { .kind = avr_timer_wgm_fast_pwm, .size=8 } #define AVR_TIMER_WGM_FASTPWM9() { .kind = avr_timer_wgm_fast_pwm, .size=9 } #define AVR_TIMER_WGM_FASTPWM10() { .kind = avr_timer_wgm_fast_pwm, .size=10 } +#define AVR_TIMER_WGM_FCPWM8() { .kind = avr_timer_wgm_fc_pwm, .size=8 } +#define AVR_TIMER_WGM_FCPWM9() { .kind = avr_timer_wgm_fc_pwm, .size=9 } +#define AVR_TIMER_WGM_FCPWM10() { .kind = avr_timer_wgm_fc_pwm, .size=10 } #define AVR_TIMER_WGM_OCPWM() { .kind = avr_timer_wgm_pwm, .top = avr_timer_wgm_reg_ocra } #define AVR_TIMER_WGM_ICPWM() { .kind = avr_timer_wgm_pwm, .top = avr_timer_wgm_reg_icr } @@ -84,6 +88,8 @@ typedef struct avr_timer_wgm_t { typedef struct avr_timer_t { avr_io_t io; char name; + uint16_t trace_flags; + avr_regbit_t disabled; // bit in the PRR avr_io_addr_t r_tcnt, r_icr;