/* 
 * File:   dimmer_led_3.c
 * Author: corrado
 */

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>

int TIME_ON[] =  { 5,   10,  20,  50, 100, 250};
int TIME_OFF[] = {250, 245, 235, 205, 155,   5};

#define OFF   0
#define ON    1

#define KEY_STATE_NONE    0
#define KEY_STATE_PRESSED 1

int main(int argc, char** argv) {

    char state, duty, key_state;

    TRISAbits.RA3 = 1;
    TRISAbits.RA2 = 1;

    TRISBbits.TRISB0 = 0; // output
    TRISBbits.TRISB1 = 0; // output
    TRISBbits.TRISB2 = 0; // output
    TRISBbits.TRISB3 = 0; // output
    TRISBbits.TRISB4 = 0; // output
    TRISBbits.TRISB5 = 0; // output

    duty = 0;
    key_state = KEY_STATE_NONE;

    T2CONbits.TMR2ON = 0; // stop the timer
    T2CONbits.T2CKPS = 0b10; // 1:16 prescaler
    T2CONbits.T2OUTPS = 0b0000; // no postscaler
    TMR2 = 0; // reset timer
    PR2 = TIME_OFF[duty]; // load period register
    PIR1bits.TMR2IF = 0; // reset interrupt flag
    T2CONbits.TMR2ON = 1; // start the timer
    state = OFF;

    LATB = 0xff; // all leds off

    for (;;) {
        if (PIR1bits.TMR2IF == 1) { // period match
            if (state == OFF) {
                LATB = 0xc0; // all leds on
                PR2 = TIME_ON[duty]; // load period register
                state = ON;
            }
            else {
                LATB = 0xff; // all leds off
                PR2 = TIME_OFF[duty]; // load period register
                state = OFF;
            }
            PIR1bits.TMR2IF = 0; // reset interrupt flag
        }

        // keyboard handling
        switch(key_state) {
            case KEY_STATE_NONE:
                if (PORTAbits.RA2 == 0) { // key B pressed
                    if (duty < 5)
                        duty++;
                    key_state = KEY_STATE_PRESSED;
                }
                else if (PORTAbits.RA3 == 0) { // key A pressed
                    if (duty > 1)
                        duty--;
                    key_state = KEY_STATE_PRESSED;
                }
                break;

            case KEY_STATE_PRESSED:
                //  To change state ensure that *both pushbuttons* are released
                if (PORTAbits.RA3 == 1 && PORTAbits.RA2 == 1)
                    key_state = KEY_STATE_NONE;
                break;
        }
    }
    return (EXIT_SUCCESS);
}

