#include "header.h"

// 14.3.1 : alternate functions for led2 PB1
// - OC1A (Timer/Counter1 Output Compare Match A Output)
//   - 16.11.1 controlled by COM1A1:0 in TCCR1A
//   - Table 16-2 : Compare Output Mode, Fast PWM
//     (1 << COM1A1) | (0 << COM1A0) -> non-inverting mode
//   - Table 16-4 : set timer 1 in fast PWM mode, with top as ICR1 or OCR1A
//   - ICR1 : Input Capture Register ((1 << WGM13) | (1 << WGM12) | (1 << WGM11) | (0 << WGM10))
//   - OCR1A : Output Compare Register ((1 << WGM13) | (1 << WGM12) | (1 << WGM11) | (1 << WGM10))
//     -> if OCR1A is top, it's also duty cycle, so changing duty cycle will also change frequency
//     -> if ICR1 is top, OCR1A is duty cycle, so it can be changed independantly
// - PCINT1 (Pin Change Interrupt 1) : to interrupt when pin change, in input mode only

// calulations
// - frequency is 16Mhz -> it means that the clock runs 16 000 000 times per seconds
// - and the timer1 can store 16 bits value of cycle -> which is 2^16 = 65536
// - so it will only last 65536/16000000 = 0,004096 second
// - if i want my cycle to be 0.001 second, prescaler 1 is enough
// - if i want my cycle to be 0.01 second, which prescaler ?
//   - 8 * 0,004096 = 0.032768 -> it is enough
//   - 64 * 0,004096 = 0.262144 -> it is largely enough
// - if i choose prescaler 1 for a duration of 0.001 seconds, i need to restart the clock after how many cycles :
//   - (16000000 / 1) * 0.001 = 16000 ticks -> set ICR1 = 16000
// - if i choose prescaler 8 for a duration of 0.01 seconds, i need to restart the clock after how many cycles :
//   - (16000000 / 8) * 0.01 = 20000 ticks -> set ICR1 = 20000
// - if i choose prescaler 64 for a duration of 0.01 seconds, i need to restart the clock after how many cycles :
//   - (16000000 / 64) * 0.01 = 2500 ticks -> set ICR1 = 2500

// 16.9.3 : timer1 fast PWM

#define LED1_PWM_PRESCALER	8	// can be 1, 8, 64, 256, 1024
#define DUTY_CYCLE_PERCENT	9
#define FRQUENCY_MS			1

// use timers interruptions to varie led1 intensity using duty cycle, from 0% to 100% to 0% in 1 second
// timer1 sets the led duty cycle, timer0 change the duty cycle percentage
int main() {
	MODE_OUTPUT(LED1);
	CLEAR_ELEM(LED1);
	MODE_OUTPUT(LED2);
	CLEAR_ELEM(LED2);

	SREG |= ENABLE_GLOBAL_INTERRUPT;

	TCCR1A = (1 << WGM11);								// Table 16-4 : set fast PWM mode with TOP ICR1, so we can use OCR1A for duty cycle and keep ICR1 for frequency
	TCCR1B = (1 << WGM13) | (1 << WGM12);

	TCCR1A |= (1 << COM1A1);							// Table 16-2 : set non-inverting mode to trigger OC1A on fast PWM

	TCCR1B |= PRESCALE_SET(LED1_PWM_PRESCALER);			// Table 16-5 : set the appropriate prescale values

	ICR1 = TIME_MS(FRQUENCY_MS, LED1_PWM_PRESCALER);	// top value for Xms

	OCR1A = PERCENT(DUTY_CYCLE_PERCENT, ICR1);			// duty cycle frequence

    while (1);
}
