/******************************************************************************
 * 
 * Glove, by Zach Taylor - 12/13/04
 *
 * glove.c -- Control the glove.
 * 
 *****************************************************************************/


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/ina90.h>

// LCD Definitions
#define E PD3
#define RS PD1
#define DB7 PD7
#define DB6 PD6
#define DB5 PD5
#define DB4 PD4

#define lcd_ddr DDRD
#define lcd_port PORTD

// LED Definitions
#define on_ddr DDRD
#define on_port PORTD
#define on_pin PD0

#define contact_ddr DDRB
#define contact_port PORTB
#define contact_pin PB2

#define settle_delay 10000

// RF Out Definitions
#define rf_out_port PORTC
#define rf_out PC0

// A/D Definitions
#define sensor_cap_3 PA3
#define sensor_res_3 PA2

// Button Definitions
#define button_ddr DDRC
#define button_port PINC
#define button_pin PC7

void led_on();
void contact_on();

void delay();
void init_lcd();
void lcd_tx( uint8_t );
void lcd_tx_char( uint8_t );
void lcd_tx_int( uint8_t );
void lcd_tx_int16( uint16_t );
void lcd_clear();
void lcd_2nd_line();
void lcd_zero_pos();
void button_call();

void init_ad3();
void settle();
uint16_t check_3();

int main()
{
    OSCCAL = 0xFF;

    // disable jtag
    MCUCSR |= ( 1 << JTD );
    MCUCSR |= ( 1 << JTD );

    DDRA = 0;
    DDRB = 0;
    DDRC = 0;
    DDRD = 0;


    //PORTD |= (1 << PD0);

    //DDRA |= ( 1 << sensor_res_3);

    //DDRA &= ~( 1 << sensor_cap_3);
    //DDRC |= ( ( 1 << rf_out ) | ( 1 << PC1) );
    //DDRC &= ~( 1 << PC7);
    DDRC |= ( 1 << PC0);
    DDRD |= ( 1 << E ) |
            ( 1 << RS ) |
            ( 1 << DB7 ) |
            ( 1 << DB6 ) |
            ( 1 << DB5 )|
            ( 1 << DB4 )| ( 1 << PD0);

/*
    DDRA |= ( 1 << PA2);
    DDRA &= ~( 1 << PA3);
    PORTA |= ( 1 << PA2);
    while (!(PINA & (1 << PA3)));
*/

    //PORTD &= ~(1 << PD0);
    //on_port &= ~( 1 << on_pin);

    //contact_on();

    //rf_out_port = ( 1 << rf_out );

    init_lcd();
    lcd_zero_pos();

    lcd_tx_char( 'T' );
    lcd_tx_char( 'o' );
    lcd_tx_char( 'u' );
    lcd_tx_char( 'c' );
    lcd_tx_char( 'h' );

    lcd_2nd_line();
    lcd_tx_char( 'F' );
    lcd_tx_char( 'i' );
    lcd_tx_char( 'n' );
    lcd_tx_char( 'g' );
    lcd_tx_char( 'e' );
    lcd_tx_char( 'r' );
    lcd_tx_char( 's' );

    while (1) {
        if (PINC & ( 1 << PC7) ) {
            PORTC |= ( 1 << PC0 );
        } if ( !(PINC & ( 1 << PC7) ) ) {
            PORTC &= ~( 1 << PC0);
        }
    }
            

/*
    init_ad3();
    while ( 1 == 1) {
        lcd_2nd_line();
        lcd_tx_int16 ( check_3() );
    }
*/
}

void led_on()
{
    on_ddr |= ( 1 << on_pin);
    on_port |= ( 1 << on_pin);
}

void contact_on()
{
    contact_ddr |= ( 1 << contact_pin);
    contact_port |= ( 1 << contact_pin);
}

void init_lcd() 
{
    // initialization sequence
    delay();
    lcd_tx( ( 1 << DB5 ) | ( 1 << DB4 ) );    
    lcd_tx( ( 1 << DB5 ) | ( 1 << DB4 ) );    
    lcd_tx( ( 1 << DB5 ) | ( 1 << DB4 ) );    

    // set the 4-bit interface
    lcd_tx( 1 << DB5 );
    
    // set two lines and a 5x7 font
    lcd_tx( 1 << DB5 );
    lcd_tx( 1 << DB7 );

    // turn the display on/off
    lcd_tx( 0 );
    lcd_tx( ( 1 << DB7 ) | ( 1 << DB6 ) | ( 1 << DB5 ) );

    // entry mode set
    lcd_tx( 0 );
    lcd_tx( ( 1 << DB6 ) | ( 1 << DB5 ) );    

}

void lcd_tx( uint8_t a ) 
{
    lcd_port = ( a | ( 1 << on_pin ) );
    lcd_port |= ( 1 << E );
    _NOP();
    _NOP();
    _NOP();
    _NOP();
    _NOP();
    lcd_port &= ~( 1 << E );
    delay();

}

void lcd_tx_int( uint8_t num )
{
    uint8_t i;

    i = 0;
    while ( num > 99 )
    {
        num = num - 100 ;
        i++;   
    }
    lcd_tx_char ( i + '0' );
 
    i = 0;
    while ( num > 9 )
    {
        num = num - 10 ;
        i++;   
    }
   lcd_tx_char ( i + '0' );
 
    i = 0;
    while ( num > 0 )
    {
        num = num - 1 ;
        i++;   
    }
    lcd_tx_char ( i + '0' );
 
}

void lcd_tx_int16( uint16_t num )
{
    uint8_t i;

    i = 0;
    while ( num > 9999 )
    {
        num = num - 10000 ;
        i++;   
    }
    lcd_tx_char ( i + '0' );

    i = 0;
    while ( num > 999 )
    {
        num = num - 1000 ;
        i++;   
    }
    lcd_tx_char ( i + '0' );

    i = 0;
    while ( num > 99 )
    {
        num = num - 100 ;
        i++;   
    }
    lcd_tx_char ( i + '0' );
 
    i = 0;
    while ( num > 9 )
    {
        num = num - 10 ;
        i++;   
    }
   lcd_tx_char ( i + '0' );
 
    i = 0;
    while ( num > 0 )
    {
        num = num - 1 ;
        i++;   
    }
    lcd_tx_char ( i + '0' );
 
}

void lcd_tx_char( uint8_t a )
{
    lcd_tx( ( a ) | ( 1 << RS) );
    lcd_tx( ( a << 4 ) | ( 1 << RS) );

}

void delay() 
{
    uint32_t i;
    for (i = 0; i < 100000; i++);

}

void lcd_clear()
{
    lcd_tx ( 0 );
    lcd_tx ( 0x10 );

}

void lcd_zero_pos()
{
    lcd_tx( 1 << DB7 );
    lcd_tx( 0 );

}

void lcd_2nd_line ()
{
    lcd_tx( ( ( 1 << DB7 ) + ( 1 << DB6) ) );
    lcd_tx( 0 );
   
}

uint16_t check_3()
{
    uint8_t low_up;    
    uint8_t high_up;
    uint16_t dn;
    uint16_t up;

    // settle sample and start upward step response
    PORTA &= ~( 1 << PA2);
    settle();
    PORTA |= ( 1 << PA2);

    // wait for delay
    _NOP();

    // read response
    // start conversion
    ADCSRA |= ( 1 << ADSC );

    // is this right for "sbic ADCSR, ADSC"?  apparently
    while ( ( ADCSRA & ( 1 << ADSC ) ) != 0 ) {
        //ADCSRA |= ( 1 << ADSC );
    }

    //save conversion
    // save low byte
    low_up = ADCL;
    // save high byte
    high_up = ADCH;

    // start downward step response
    PORTA &= ~( 1 << PA2 );

    // wait for delay
    _NOP();

    // read response
    // start conversion
    ADCSRA |= ( 1 << ADSC );

    // is this right for "sbic ADCSRA, ADSC"?  apparently
    while ( ( ADCSRA & ( 1 << ADSC ) ) != 0 ) {
        //ADCSRA |= ( 1 << ADSC );
    }

/*
    //send downward conversion
    lcd_tx_int ( ADCL );          //dn_lo
    lcd_tx_char ( ' ' );
    lcd_tx_int ( ADCH );          //dn_hi

    lcd_2nd_line();
    //send upward conversion
    lcd_tx_int ( low_up );        //up_lo
    lcd_tx_char ( ' ');
    lcd_tx_int ( high_up );       //up_hi
*/

    //converted python code
    dn = ADCL + 256 * ADCH;
    up = low_up + 256 * high_up;
    //lcd_tx_int ( up );

    return up;
}

void settle()
{
    uint32_t i;

    for ( i = 0; i < settle_delay; i++) {
    }
}

void init_ad3()
{
    DDRA |= ( 1 << PA2 ); 
    PORTA |= ( 1 << PA2 );

    ADMUX &= ~( 1 << REFS1 );
    ADMUX &= ~( 1 << REFS0 );
    ADMUX &= ~( 1 << ADLAR );
    ADMUX &= ~( 1 << MUX4 );
    ADMUX &= ~( 1 << MUX3 );
    ADMUX &= ~( 1 << MUX2 );
    ADMUX |= ( 1 << MUX1 );
    ADMUX |= ( 1 << MUX0 );

    ADCSRA |= ( 1 << ADEN );
    ADCSRA &= ~( 1 << ADATE );
    ADCSRA &= ~( 1 << ADIE );
    ADCSRA |= ( 1 << ADPS2 );
    ADCSRA |= ( 1 << ADPS1 );
    ADCSRA |= ( 1 << ADPS0 );
}

void button_call()
{
    while ( button_port & ( 1 << button_pin) ) {}
    while ( !(button_port & ( 1 << button_pin)) ){}

}
