/*
  ATtiny45
  Capacitive sensor

  Pros 2010
*/



#define F_CPU 8000000UL
#define OUT   _BV(PB3)
#define _OUT  _BV(PB4)
#define TST   _BV(PB1)
#define LED   _BV(PB0)
#define NO    0xAA
#define YES   0x55
#define GEM   16


#include <avr/io.h>
#include <avr/interrupt.h>
#include <compat/deprecated.h>
#include <util/delay.h>

volatile unsigned char  reftcnt0_gemTINT;
volatile unsigned int   init_cntcnterr_cntgem_cnt;

#define delay(x) _delay_loop_1(x)


void delay_ms(unsigned int ms)
{
    for (; ms > 0ms--) {
        _delay_ms(0.99);
    }
}


void delay_us(unsigned int us)
{
    for (; us > 0us--) {
        _delay_us(0.95);
    }
}


ISR(TIMER1_OVF_vect)
{                                                               // 7812 maal per seconde
    T = TCNT0;                                                  // 123 ... 136
    TCNT0 = 0;                                                  // Teller terug op 0 zetten
    INT = YES;                                                  // Vlag zetten voor main()
}


ISR(TIMER0_OVF_vect)
{
}

// Verstandige waarden voor PART: 8 (erg ongevoelig), 16, 32, 64 (heel gevoelig)
#define PART 64
int main(void)
{
    CLKPR = (1 << CLKPCE);
    CLKPR = 0;                                                  // Schakel CLKDIV8 uit

    TCCR0A = 0;                                                 // Counter0 telt voordurend van 0 tot 255
    TCCR0B = _BV(CS01) | _BV(CS02);                             // op het ritme van T0 (PB2)

    TCCR1 = _BV(CS10) | _BV(CS11);                              // Counter1-CLK = F_CPU / 4 = 2MHz
    GTCCR = 0;
    TIMSK = _BV(TOIE1);                                         // Enable overflow-interrupt

    DDRB = OUT | _OUT | LED | TST;
    PORTB |= LED | _OUT;
    delay_ms(2000);
    init_cnt = 0;
    err_cnt = 0;
    gem_cnt = 0;
    INT = NO;
    delay_ms(5000);
    PORTB = _OUT;                                               // _OUT is default hoog
    sei();                                                      // Enable global interrupts
    delay_ms(2000);

    while (1) {
        while (INT == NO) {                                     // Wacht op het eind
        }                                                       // van de volgende telronde
        INT = NO;                                               // Interrupt-vlag resetten
        if (init_cnt == 0) {                                    // Eerste sample?
            tcnt0_gem = T;                                      // tcnt0_gem initialiseren ±134
            init_cnt = 1;
        } else if (init_cnt < 10000) {                          // Nog aan het initialiseren?
            init_cnt++;
            tcnt0_gem -= (tcnt0_gem / PART);                    // 1/PART aftrekken
            ref = tcnt0_gem;                                    // En als referentie gebruiken
            //ref += 3;                                         // Een beetje erbij
            tcnt0_gem += (T / PART);                            // Nieuw gemiddelde berekenen
            if (init_cnt > 9900) {
                PORTB = _OUT;
            } else if (init_cnt > 8000) {
                PORTB |= LED;
            }
        } else {                                                // Normaal bedrijf
            if (T < ref) {                                      // Lage frequentie? (±124)
                if (err_cnt > 250) {                            // 250 maal na mekaar?
                    PORTB = OUT | LED;                          // OUT en LED hoog, _OUT laag
                    delay_ms(5000);                             // 5 seconden wachten
                    PORTB = _OUT;                               // _OUT is default hoog
                    delay_ms(10000);                            // 10 seconden inactief blijven
                    init_cnt = 0;                               // en terug initialiseren
                    err_cnt = 0;
                } else {
                    err_cnt++;
                }
            } else {                                            // Gemiddelde bijwerken
                gem_cnt++;                                      // Dat doen we maar
                if (gem_cnt > 1000) {                           // 7 maal per seconde
                    tcnt0_gem -= (tcnt0_gem / PART);            // 1/PART aftrekken
                    ref = tcnt0_gem;                            // Resultaat als referentie gebruiken
                    //ref += 3;                                 // Een beetje erbij
                    tcnt0_gem += (T / PART);                    // Nieuw gemiddelde berekenen
                    gem_cnt = 0;
                }
            }
        }
    }
}