/* 
 * Program to solve Part 4 of Lab 6 
 * Use Input Capture 2 Interrupt to measure time between two falling edges
 * Use Output Compare 2 Interrupt to generate a 1 kHz square wave
 */

#include <hc11.h>

#define TRUE 1
#define HALF_PERIOD 62     /* 125 clock cycles in a period for 1 kHz; 62.5 in half */

int write_to_serial(unsigned short n);
void tic2_isr(void);
void toc2_isr(void);

unsigned short first_edge;   /* Time of first edge */
unsigned short second_edge;  /* Time of second edge */
unsigned short which_edge;   /* Used to let ISR know which time to set */

main()
{
    TMSK2 = (TMSK2 | 0x03);  /* 8 us clock to timer subsystem */

    /*
     *  Set up Input Capture 2
     */
    
    TCTL2 = (TCTL2 | 0x08) & ~0x04;  /* Capture falling edge on TIC2 */

    TIC2_JMP = JMP_OP_CODE;  /* Set the TIC2 interrupt vector      */
    TIC2_VEC = tic2_isr;     /* to point to the tic2_isr() routine */
    
    TMSK1 = TMSK1 | 0x02;    /* Set Bit 1 (IC2I bit) in TMSK1  */
                             /*   to enable the TIC2 interrupt */

    TFLG1 = 0x02;            /* Clear TIC2 flag before enabling ints */

    which_edge = 1;          /* 1st time in interrupt, capture first edge */

    /*
     * Done with Input Capture 2 setup
     */

    /*
     *  Set up Output Compare 2
     */
    
    TCTL1 = (TCTL1 | 0x40) & ~0x80;  /* Toggle on successful compare */

    TOC2_JMP = JMP_OP_CODE;  /* Set the TOC2 interrupt vector      */
    TOC2_VEC = toc2_isr;     /* to point to the toc2_isr() routine */
    
    TMSK1 = TMSK1 | 0x40;    /* Set Bit 6 (OC2I bit) in TMSK1  */
                             /*   to enable the TOC2 interrupt */

    TFLG1 = 0x40;            /* Clear TOC2 flag before enabling ints */

    /*
     * Done with Output Compare 2 setup
     */

    which_edge = 1;          /* 1st time in interrupt, capture first edge */

    enable();                /* Enable interrupts (clear I bit in CCR) */

    while (TRUE) 
    { 
        if (which_edge == 3)  /* Got both edges if which_edge == 3 */
        {
            write_to_serial(second_edge - first_edge);  /* Print time diff */
            which_edge = 1;   /* Next time in will be for first edge */
        }
    }
}

#pragma interrupt_handler tic2_isr
void tic2_isr(void)
{
    if (which_edge == 1)        /* Get time of first edge if which_edge == 1 */
    {
        first_edge = TIC2;      /* get time */
        which_edge = 2;         /* Next time will grab time of second edge */
    }
    else if (which_edge == 2)   /* Get time of second edge if which_edge == 2 */
    {
        second_edge = TIC2;     /* get time */
        which_edge = 3;         /* Tell main program time got both edges */
    }

    TFLG1 = 0x02;               /* Clear source of interrupt */
}

#pragma interrupt_handler toc2_isr
void toc2_isr(void)
{
    TOC2 = TOC2 + HALF_PERIOD;  /* Set time for next compare */

    TFLG1 = 0x40;               /* Clear source of interrupt */
}

/* Routine to write an integer to the serial port */
int write_to_serial(unsigned short n)
{   
    char i;
    unsigned char t,c[6];

    for (i=3;i>=0;i--)
    {
        t = (n&0x0f);
        if (t < 10)
            c[i] = t + 48;
        else
            c[i] = t + 55;

        n = n >> 4;
    }
    c[4] = 0x0d;
    c[5] = 0x0a;
    for (i=0;i<6;i++)
    {
        while (!(SCSR&0x80)) ;
        SCDR = c[i];
    }
}