/*
    5/21/02
    Nathan Seidle
    nathan.seidle@colorado.edu
    
    Serial Out Started on 5-21
    rs_out Perfected on 5-24
    
    1Wire Serial Comm works with 4MHz Xtal
    Connect Serial_Out to Pin2 on DB9 Serial Connector
    Connect Pin5 on DB9 Connector to Signal Ground
    9600 Baud 8-N-1
    
    5-21 My first real C and Pic program.
    5-24 Attempting 20MHz implementation
    5-25 20MHz works
    5-25 Serial In works at 4MHz
    5-25 Passing Strings 9:20
    5-25 Option Selection 9:45

    6-9  'Stdio.c' created. Printf working with %d and %h
    7-20 Added a longer delay after rs_out
         Trying to get 20MHz on the 16F873 - I think the XTal is bad.
         20MHz also needs 5V Vdd. Something I dont have.
    2-9-03 Overhauled the 4MHz timing. Serial out works very well now.
    
    6-16-03 Discovered how to pass string in cc5x
        void test(const char *str);
        test("zbcdefghij"); TXREG = str[1];
        
        Moved to hardware UART. Old STDIO will be in goodworks.
        
        Works great! Even got the special print characters (\n, \r, \0) to work.
        

*/

//Clock is defined in Delay.c!!!

int counter;

//Setup the hardware UART TX module
void enable_uart_TX(bit want_ints)
{

#ifdef Crazy_Osc
    #ifdef Baud_9600
    SPBRG = 32; //20MHz for 9600 Baud
    #endif
#endif

#ifdef HS_Osc
    #ifdef Baud_9600
    SPBRG = 32; //20MHz for 9600 Baud
    #endif

    #ifdef Baud_4800
    SPBRG = 64; //20MHz for 4800 Baud
    #endif
#endif


    BRGH = 0; //Normal speed UART

    SYNC = 0;
    SPEN = 1;

    if(want_ints) //Check if we want to turn on interrupts
    {
        TXIE = 1;
        PEIE = 1;
        GIE = 1;
    }

    TXEN = 1; //Enable transmission
}    

//Setup the hardware UART RX module
void enable_uart_RX(bit want_ints)
{

#ifdef HS_Osc
    #ifdef Baud_9600
    SPBRG = 32; //20MHz for 9600 Baud
    #endif

    #ifdef Baud_4800
    SPBRG = 64; //20MHz for 4800 Baud
    #endif
#endif

    BRGH = 0; //Normal speed UART

    SYNC = 0;
    SPEN = 1;

    CREN = 1;

    //WREN = 1;

    if(want_ints) //Check if we want to turn on interrupts
    {
        RCIE = 1;
        PEIE = 1;
        GIE = 1;
    }

}    

//Sends nate to the Transmit Register
void rs_out(uns8 nate)
{
    //TXEN = 1; //Enable transmission
    TXREG = nate;
    while(TXIF == 0);

    //TXREG = 0;
    //TXEN = 0; //Disable transmission
}


//Returns ASCII Decimal and Hex values
uns8 bin2Hex(char x)
{
   skip(x);
   #pragma return[16] = "0123456789ABCDEF"
}

//Prints a string including variables
void printf(const char *nate, uns8 my_byte)
{
  
//#pragma rambank 1
    uns8 i, k, m;
    uns8 high_byte = 0, low_byte = 0;
    uns8 y, z;
    
    for(i = 0 ; ; i++)
    {
        k = nate[i];

        if (k == '\0') 
            break;

        else if (k == '%') //Print var
        {
            i++;
            k = nate[i];

            if (k == '\0') 
                break;
            else if (k == '\\') //Print special characters
            {
                i++;
                k = nate[i];
                
                rs_out(k);
                

            } //End Special Characters
            else if (k == 'b') //Print Binary
            {
                for( m = 0 ; m < 8 ; m++ )
                {
                    if (my_byte.7 == 1) rs_out('1');
                    if (my_byte.7 == 0) rs_out('0');
                    if (m == 3) rs_out(' ');
                    
                    my_byte = my_byte << 1;
                }
            } //End Binary               
            else if (k == 'd') //Print Decimal
            {
                /*if (my_byte.7 == 1)
                {
                    rs_out('-');
                    my_byte.7 = 0;
                }*/
                
                z = my_byte;
                
                y = z / 100;
                z = z % 100;
                if (y != 0)
                    rs_out(bin2Hex(y)); //Print 100s
            
                y = z / 10;
                z = z % 10;
                if (y != 0)
                    rs_out(bin2Hex(y)); //Print 10s
            
                rs_out(bin2Hex(z)); //Print 1s 
            } //End Decimal
            else if (k == 'h') //Print Hex
            {
                high_byte.3 = my_byte.7;
                high_byte.2 = my_byte.6;
                high_byte.1 = my_byte.5;
                high_byte.0 = my_byte.4;
            
                low_byte.3 = my_byte.3;
                low_byte.2 = my_byte.2;
                low_byte.1 = my_byte.1;
                low_byte.0 = my_byte.0;
        
                rs_out('0');
                rs_out('x');
            
                rs_out(bin2Hex(high_byte));
                rs_out(bin2Hex(low_byte));
            } //End Hex
            else if (k == 'f') //Print Float
            {
                rs_out('!');
            } //End Float
            else if (k == 'u') //Print Direct Character
            {
                //All ascii characters below 20 are special and screwy characters
                if(my_byte > 20) rs_out(my_byte);
            } //End Direct
                        
        } //End Special Chars           

        else
            rs_out(k);
    }    
}


//Bit banging functions for direct connect from pic to serial port comm
//No MAX232 chip required - dirty, but it works
//==================================================
void rs_wait(void)
{

#ifdef Clock_4MHz
    int i;
    //for(i = 0 ; i < counter ; i++);
    for(i = 0 ; i < 6 ; i++);
#endif

#ifdef HS_Osc
    int i;
    //for(i = 0 ; i < counter ; i++);
    for(i = 0 ; i < 36 ; i++);
#endif
    
}

//Sends nate out at 9600 Baud
void rs_out_bb(uns8 nate)
{
#ifdef Clock_4MHz
#pragma rambank 1
    int l;

    Serial_Out_BB = 1;
    delay_us(9);
    //rs_wait();
    nop();
    nop();
    nop();

    for(l = 0 ; l < 8 ; l++)
    {
        Serial_Out_BB = !nate.0;
        nate = rr(nate);
        delay_us(9);
        //rs_wait();
    }

    Serial_Out_BB = 0;
    //rs_wait();
    
    //6-20-02 Needed a long wait time. Stuff was getting messed up
    delay_us(10);
    //delay_ms(1);
   
#endif

#ifdef HS_Osc
#pragma rambank 0
    int l;

    Serial_Out_BB = 1;
    rs_wait();

    for(l = 0 ; l < 8 ; l++)
    {
        Serial_Out_BB = !nate.0;
        nate = rr(nate);
        rs_wait();
    }

    Serial_Out_BB = 0;
    //rs_wait();
    
    //6-20-02 Needed a long wait time. Stuff was getting messed up
    delay_ms(1);
#endif

}

//Prints a string including variables
void printf_bb(const char *nate, uns8 my_byte)
{
    //Display byte
  
#pragma rambank 0
    uns8 i, k, m;
    uns8 high_byte = 0, low_byte = 0;
    uns8 y, z;
    
    for(i = 0 ; ; i++)
    {
        k = nate[i];

        if (k == '\0') 
            break;

        else if (k == '%') //Print var
        {
            i++;
            k = nate[i];

            if (k == '\0') 
                break;
            else if (k == 'b') //Print Binary
            {
                for( m = 0 ; m < 8 ; m++ )
                {
                    if (my_byte.7 == 1) rs_out_bb('1');
                    if (my_byte.7 == 0) rs_out_bb('0');
                    
                    if (m == 3) rs_out_bb(' ');
                    
                    my_byte = my_byte << 1;
                }
            } //End Binary               
            else if (k == 'd') //Print Decimal
            {
                /*if (my_byte.7 == 1)
                {
                    rs_out_bb('-');
                    my_byte.7 = 0;
                }*/
                
                z = my_byte;
                
                y = z / 100;
                z = z % 100;
                if (y != 0)
                    rs_out_bb(bin2Hex(y)); //Print 100s
            
                y = z / 10;
                z = z % 10;
                if (y != 0)
                    rs_out_bb(bin2Hex(y)); //Print 10s
            
                rs_out(bin2Hex(z)); //Print 1s 
            } //End Decimal
            else if (k == 'h') //Print Hex
            {
                high_byte.3 = my_byte.7;
                high_byte.2 = my_byte.6;
                high_byte.1 = my_byte.5;
                high_byte.0 = my_byte.4;
            
                low_byte.3 = my_byte.3;
                low_byte.2 = my_byte.2;
                low_byte.1 = my_byte.1;
                low_byte.0 = my_byte.0;
        
                rs_out_bb('0');
                rs_out_bb('x');
            
                rs_out_bb(bin2Hex(high_byte));
                rs_out_bb(bin2Hex(low_byte));
            } //End Hex
            else if (k == 'f') //Print Float
            {
                rs_out_bb('!');
            } //End Float

            else if (k == 'u') //Print Direct Character
            {
                if(my_byte > 20) rs_out(my_byte);
            } //End Direct
                        
        } //End Special Chars           

        else
            rs_out_bb(k);
    }    
}

//Returns nate at 9600 Baud
int rs_in_bb(void)
{

#ifdef Clock_4MHz
    uns8 j, nate, counter = 0;

    //while (Serial_In == 0);
    while (Serial_In == 0 && counter < 250)
    {
        counter++;
        if (counter > 245) return(0);
    }

    for(j = 0 ; j < 8 ; j++)
    {
        nate.7 = !Serial_In;
        nate = rr(nate);
        rs_wait();
    }
    
    return(nate);
#endif

#ifdef HS_Osc
    uns8 j, nate, counter = 0;

    //while (Serial_In == 0);
    while (Serial_In_BB == 0 && counter < 250)
    {
        counter++;
        if (counter > 245) return(0);
    }

    for(j = 0 ; j < 8 ; j++)
    {
        nate.7 = !Serial_In_BB;
        nate = rr(nate);
        rs_wait();
    }
    
    return(nate);
#endif    

}