//LAB 7 CODE - Receiver
//Michael Jardin
//Nick Liu
//Monday, 7:30-10:30 Lab


#include <Mega163.h>

//timeout values for each task
#define t1         20

#define max        255                     //value that the PWM wave counts up to
#define foward     0x08                    //signal for each going in the foward direction
#define idle       128                     //PWM value used for engines off
#define off        0x08                    //transmission byte indicating hovercraft should be off

//the subroutines
void task1(void);                          //Parses receive byte into voltages for motors
void initialize(void);                     //sets up the mcu
void gets_int(void);                       //nonblocking receive interrupt scheme

//define variables
unsigned char reload;                      //timer 0 reload to set 1 mSec
unsigned char time1;                       //keeps track of current time of task
unsigned char signal;                      //temporary variable that is parsed to correct values for motors
unsigned char r_ready;                     //flag for receive done receive interrupt
unsigned char r_char;                      //current byte that is received
unsigned char rightD, rightV, leftD, leftV;//variables used to store direction and voltage of respective motors
 

//Lookup table to determine correct voltage for motors
flash float voltages[16]=
    {7*(max/14), 6*(max/14), 5*(max/14), 4*(max/14), 3*(max/14),
    2*(max/14), (max/14), 0, 7*(max/14), 8*(max/14), 9*(max/14),
    10*(max/14), 11*(max/14), 12*(max/14), 13*(max/14), 14*(max/14)};

//**********************************************************
//timer 0 overflow ISR

interrupt [TIM0_OVF] void timer0_overflow(void)
{
    TCNT0=reload;                         //reload to force 1 mSec overflow
    if (time1>0) --time1;                 //Decrement the three times if they are not already zero
}

//**********************************************************
//UART character-ready ISR

interrupt [UART_RXC] void uart_rec(void)
{
    r_char=UDR;                           //get a char
    signal=r_char;
    UCSRB.7=0;                            //stop rec ISR
}

//**********************************************************
//Entry point and task scheduler loop

void main(void)
{
    initialize();
    while(1)                              //main task scheduler loop -- never exits
        if (time1==0) task1();
}

//**********************************************************
void task1(void)
{
    time1=t1;

    PORTB = signal;                     //for debugging

    if (signal == off){                 //when transmitter turns hovercraft off, will constantly send off signal
        PORTC.0 = 0x00;                 //make sure the hovercraft is off
        OCR1A = idle;                   //set both motors to idle
        OCR1B = idle;
    }
    else {

        PORTC.0 = 0xff;                 //make sure hovercraft is on

        rightV = (signal & 0x07);       //right voltage magnitude = bits 0-3
        rightD = (signal & 0x08);       //right direction = bit 4 (1-foward, 0-reverse)
        signal >>= 4;                   //shift bits 4-7 right so now bits 0-3
        leftV = (signal & 0x07);        //left voltage magnitude = bits 0-3
        leftD = (signal & 0x08);        //left direction = bit 4 (1-foward, 0-reverse)

        if (rightD == foward)           //if right motor is forward
            OCR1A = voltages[8+rightV]; //read off voltage from 2nd half of table
        else
            OCR1A = voltages[rightV];   //else read from first half of table

        if (leftD == foward)            //repeat for left engine
            OCR1B = voltages[8+leftV];
        else
            OCR1B = voltages[leftV];
        }

    signal = off;                       //signal will go back on only when transmitter is TXing
    r_ready=1;                          //ready to receive another data byte
    if (r_ready ) gets_int();           //start receive interrupt

}

//**********************************************************
// -- non-blocking keyboard check initializes ISR-driven
// receive. This routine merely sets up the ISR, which then
//does all the work of getting a command.

void gets_int(void)
{
    r_ready=0;
    UCSRB.7=1;                          //turn on transmit interrupt
}

//**********************************************************
//Set it all up

void initialize(void)
{
    //Set UART communication
    UCSRB = 0x10;
    UBRR = 255;

    //set up the ports
    DDRD=0xfc;                         // PORT D.0 and D.1 are inputs, rest are outputs
    DDRC=0xff;                         // PORT C is an ouput (power)
    PORTC.0=0x00;                      // hovercraft is initally off


    //set up timer 0
    reload=256-62;                     //value for 1 Msec
    TCNT0=reload;                      //preload timer 1 so that is interrupts after 1 mSec.
    TCCR0=3;                           //prescalar to 64
    TIMSK=1;                           //turn on timer 0 overflow ISR

    //set up timer 1
    TCCR1B = 1;                        //disable timer 1
    TCNT1 = 0;                         //and zero the timer
    TCCR1A = 0b10100001;               //page 43 - PWM stuff
    OCR1A=idle;                        //right motor off
    OCR1B=idle;                        //left motor off

    //init the task timers
    time1=t1;

    signal = off;                      //keep the hovercraft in the off state
    r_ready = 1;                       //start receiving signal from transmitter

    //crank up the ISRs
    #asm
        sei
    #endasm
}