static void avr_timer_configure( avr_timer_t * p, uint32_t clock, uint32_t top, uint8_t reset) { p->tov_cycles = 0; p->tov_top = top; p->tov_cycles = clock * (top+1); AVR_LOG(p->io.avr, LOG_TRACE, "TIMER: %s-%c TOP %.2fHz = %d cycles = %dusec\n", __FUNCTION__, p->name, (p->io.avr->frequency / (float)p->tov_cycles), (int)p->tov_cycles, (int)avr_cycles_to_usec(p->io.avr, 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); uint32_t comp_cycles = clock * (ocr + 1); p->comp[compi].comp_cycles = 0; if (p->trace & (avr_timer_trace_compa << compi)) printf("%s-%c clock %f top %d OCR%c %d\n", __FUNCTION__, p->name, (float)(p->io.avr->frequency / clock), top, 'A'+compi, ocr); if (ocr && ocr <= top) { p->comp[compi].comp_cycles = comp_cycles; // avr_hz_to_cycles(p->io.avr, fa); if (p->trace & (avr_timer_trace_compa << compi)) printf( "TIMER: %s-%c %c %.2fHz = %d cycles\n", __FUNCTION__, p->name, 'A'+compi, (float)(p->io.avr->frequency / ocr), (int)p->comp[compi].comp_cycles); } } if (p->tov_cycles > 1) { if (reset) { avr_cycle_timer_register(p->io.avr, p->tov_cycles, avr_timer_tov, p); // calling it once, with when == 0 tells it to arm the A/B/C timers if needed p->tov_base = 0; avr_timer_tov(p->io.avr, p->io.avr->cycle, p); } else { uint64_t orig_tov_base = p->tov_base; avr_cycle_timer_register(p->io.avr, p->tov_cycles - (p->io.avr->cycle - orig_tov_base), avr_timer_tov, p); // calling it once, with when == 0 tells it to arm the A/B/C timers if needed p->tov_base = 0; avr_timer_tov(p->io.avr, orig_tov_base, p); } } }
static void avr_timer_tcnt_write(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 tcnt = _timer_get_tcnt(p); if (!p->tov_top) return; if (tcnt >= p->tov_top) tcnt = 0; // this involves some magicking // cancel the current timers, recalculate the "base" we should be at, reset the // 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); avr_cycle_timer_cancel(avr, avr_timer_compb, p); avr_cycle_timer_cancel(avr, avr_timer_compc, p); uint64_t cycles = (tcnt * p->tov_cycles) / p->tov_top; // printf("%s-%c %d/%d -- cycles %d/%d\n", __FUNCTION__, p->name, tcnt, p->tov_top, (uint32_t)cycles, (uint32_t)p->tov_cycles); // this reset the timers bases to the new base if (p->tov_cycles > 1) { avr_cycle_timer_register(avr, p->tov_cycles - cycles, avr_timer_tov, p); p->tov_base = 0; avr_timer_tov(avr, avr->cycle - cycles, p); } // tcnt = ((avr->cycle - p->tov_base) * p->tov_top) / p->tov_cycles; // printf("%s-%c new tnt derive to %d\n", __FUNCTION__, p->name, tcnt); }
static void avr_timer_configure(avr_timer_t * p, uint32_t clock, uint32_t top) { float t = clock / (float)(top+1); float frequency = p->io.avr->frequency; p->tov_cycles = 0; p->tov_top = top; p->tov_cycles = frequency / t; // avr_hz_to_cycles(frequency, t); AVR_LOG(p->io.avr, LOG_TRACE, "TIMER: %s-%c TOP %.2fHz = %d cycles = %dusec\n", __FUNCTION__, p->name, t, (int)p->tov_cycles, (int)avr_cycles_to_usec(p->io.avr, 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); if (ocr && ocr <= top) { p->comp[compi].comp_cycles = frequency / fc; // avr_hz_to_cycles(p->io.avr, fa); 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); } } if (p->tov_cycles > 1) { avr_cycle_timer_register(p->io.avr, p->tov_cycles, avr_timer_tov, p); // calling it once, with when == 0 tells it to arm the A/B/C timers if needed p->tov_base = 0; avr_timer_tov(p->io.avr, p->io.avr->cycle, p); } }