#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <util/delay.h>
#include <util/atomic.h>

#include "lights.h"

/*
 * Single PWM channel on OC1B (pin PB4 of Tiny45).
 * Counts from 0 to 0xFF, without OCR1C compare.
 */

static void inline enable_pll()
{
	/* Async clock */
	PLLCSR = _BV(PLLE);

	/* Synchronize to the phase lock */
	_delay_us(100);
	while ((PLLCSR & _BV(PLOCK)) == 0)
		;
	PLLCSR |= _BV(PCKE);
}

void init_pwm()
{
	power_timer1_enable();

	enable_pll();

	TCCR1 = _BV(CTC1) | _BV(CS10);	// no clock prescaling
	GTCCR = _BV(COM1B1) | _BV(PWM1B);

	OCR1C = PWM_MAX;
	OCR1B = 0;		// initial stride is 0

	DDRB  &= ~_BV(PB4); // tristate it
	PORTB &= ~_BV(PB4); // set to zero
}

void susp_pwm()
{
	DDRB &= ~(_BV( PB4 ));
	PORTB &= ~(_BV( PB4 ));
	TCCR1 = 0;
	TIMSK = 0;
	TIFR = 0;

	PLLCSR &= ~(_BV(PLLE) | _BV(PCKE));
}

void pwm_off()
{
	OCR1B = 0;
	DDRB &= ~_BV(PB4);
}

void pwm_set(uint8_t stride)
{
	OCR1B = stride;
	DDRB |= _BV(PB4);
}
