示例#1
0
static void avr_timer_reconfigure(avr_timer_t * p)
{
	avr_t * avr = p->io.avr;

	avr_timer_wgm_t zero={0};
	p->mode = zero;
	// cancel everything
	p->comp[AVR_TIMER_COMPA].comp_cycles = 0;
	p->comp[AVR_TIMER_COMPB].comp_cycles = 0;
	p->comp[AVR_TIMER_COMPC].comp_cycles = 0;
	p->tov_cycles = 0;
	
	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);

	long clock = avr->frequency;

	// only can exists on "asynchronous" 8 bits timers
	if (avr_regbit_get(avr, p->as2))
		clock = 32768;

	uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
	if (cs == 0) {
		AVR_LOG(avr, LOG_TRACE, "TIMER: %s-%c clock turned off\n", __FUNCTION__, p->name);
		return;
	}

	uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));
	uint8_t cs_div = p->cs_div[cs];
	uint32_t f = clock >> cs_div;

	p->mode = p->wgm_op[mode];
	//printf("%s-%c clock %d, div %d(/%d) = %d ; mode %d\n", __FUNCTION__, p->name, clock, cs, 1 << cs_div, f, mode);
	switch (p->mode.kind) {
		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;
		case avr_timer_wgm_pwm: {
			uint16_t top = p->mode.top == avr_timer_wgm_reg_ocra ? _timer_get_ocr(p, AVR_TIMER_COMPA) : _timer_get_icr(p);
			avr_timer_configure(p, f, top);
		}	break;
		case avr_timer_wgm_fast_pwm:
			avr_timer_configure(p, f, (1 << p->mode.size) - 1);
			break;
		default:
			AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c unsupported timer mode wgm=%d (%d)\n",
					__FUNCTION__, p->name, mode, p->mode.kind);
	}	
}
示例#2
0
static void
avr_timer_write_ocr(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_timer_comp_p comp = (avr_timer_comp_p)param;
	avr_timer_t *timer = comp->timer;
	uint16_t oldv;

	/* check to see if the OCR values actually changed */
	oldv = _timer_get_comp_ocr(avr, comp);
	avr_core_watch_write(avr, addr, v);

	switch (timer->wgm_op_mode_kind) {
		case avr_timer_wgm_normal:
			avr_timer_reconfigure(timer, 0);
			break;
		case avr_timer_wgm_fc_pwm:	// OCR is not used here
			avr_timer_reconfigure(timer, 0);
			break;
		case avr_timer_wgm_ctc:
			avr_timer_reconfigure(timer, 0);
			break;
		case avr_timer_wgm_pwm:
			if (timer->mode.top != avr_timer_wgm_reg_ocra) {
				avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(timer, AVR_TIMER_COMPA));
			} else {
				avr_timer_reconfigure(timer, 0); // if OCRA is the top, reconfigure needed
			}
			avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(timer, AVR_TIMER_COMPB));
			break;
		case avr_timer_wgm_fast_pwm:
			if (oldv != _timer_get_comp_ocr(avr, comp))
				avr_timer_reconfigure(timer, 0);
			avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM0,
					_timer_get_ocr(timer, AVR_TIMER_COMPA));
			avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM1,
					_timer_get_ocr(timer, AVR_TIMER_COMPB));
			break;
		default:
			AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c mode %d UNSUPPORTED\n",
					__FUNCTION__, timer->name, timer->mode.kind);
			avr_timer_reconfigure(timer, 0);
			break;
	}
}
示例#3
0
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);
		}
	}
}
示例#4
0
static void
avr_timer_reconfigure(
		avr_timer_t * p, uint8_t reset)
{
	avr_t * avr = p->io.avr;

	// cancel everything
	avr_timer_cancel_all_cycle_timers(avr, p, 1);

	switch (p->wgm_op_mode_kind) {
		case avr_timer_wgm_normal:
			avr_timer_configure(p, p->cs_div_value, p->wgm_op_mode_size, reset);
			break;
		case avr_timer_wgm_fc_pwm:
			avr_timer_configure(p, p->cs_div_value, p->wgm_op_mode_size, reset);
			break;
		case avr_timer_wgm_ctc: {
			avr_timer_configure(p, p->cs_div_value, _timer_get_ocr(p, AVR_TIMER_COMPA), reset);
		}	break;
		case avr_timer_wgm_pwm: {
			uint16_t top = (p->mode.top == avr_timer_wgm_reg_ocra) ?
				_timer_get_ocr(p, AVR_TIMER_COMPA) : _timer_get_icr(p);
			avr_timer_configure(p, p->cs_div_value, top, reset);
		}	break;
		case avr_timer_wgm_fast_pwm:
			avr_timer_configure(p, p->cs_div_value, p->wgm_op_mode_size, reset);
			break;
		case avr_timer_wgm_none:
			avr_timer_configure(p, p->cs_div_value, p->wgm_op_mode_size, reset);
			break;
		default: {
			uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));
			AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c unsupported timer mode wgm=%d (%d)\n",
					__FUNCTION__, p->name, mode, p->mode.kind);
		}
	}	
}
示例#5
0
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);
	}
}
示例#6
0
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));
				avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(p, AVR_TIMER_COMPB));
			}
			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:
			AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c mode %d UNSUPPORTED\n", __FUNCTION__, p->name, p->mode.kind);
			avr_timer_reconfigure(p);
			break;
	}
}