#include "RS485.h"
#include "terasic_includes.h"
#include "altera_avalon_uart_regs.h"
//#include "SEG7.h"

volatile int RS485_2_3_leddata0;
volatile int RS485_2_3_leddata1;

/////////////////////////sub routine///////////////////////////////////
//rs485 2 ISR routine
void Rs485_2_ISR(void * context,alt_u32 id)
{
    int temp0;
    //read the rx reg
    temp0=IORD_ALTERA_AVALON_UART_RXDATA(RS485_2_BASE);
    RS485_2_3_leddata0=temp0;
    //clear the rx reg
    IOWR_ALTERA_AVALON_UART_RXDATA(RS485_2_BASE, 0x0);
    //clear the irq flag
    IOWR_ALTERA_AVALON_UART_STATUS(RS485_2_BASE, 0x0);  
    //rx irq disable
    alt_irq_disable(RS485_2_IRQ);
        
}

//rs485 2 initial routine
void Rs485_2_init()
{
    //register the irq of can 0
    alt_irq_register(RS485_2_IRQ,0,Rs485_2_ISR);
    //rx irq enable
    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_2_BASE, 0x80);
    //clear the irq flag
    IOWR_ALTERA_AVALON_UART_STATUS(RS485_2_BASE, 0x0); 
    //enable the irq
    alt_irq_enable(RS485_2_IRQ);
    
    //IOWR_ALTERA_AVALON_UART_TXDATA(CAN_1_BASE,0);

}
//rs485 2 send 1 byte data
void Rs485_2_send(unsigned char data)
{
    alt_u16 status;
    //read the state reg
    status=IORD_ALTERA_AVALON_UART_STATUS(RS485_2_BASE);
    while(!(status&0x0040)) //wait until finish tx
        status=IORD_ALTERA_AVALON_UART_STATUS(RS485_2_BASE);
    //set the tx reg
    IOWR_ALTERA_AVALON_UART_TXDATA(RS485_2_BASE,data);
//     usleep(400*1000);
}

//rs485 1 send 1 byte data
void Rs485_3_send(unsigned char data)
{
    alt_u16 status;
    //read the state reg
    status=IORD_ALTERA_AVALON_UART_STATUS(RS485_3_BASE);
    while(!(status&0x0040)) //wait until finish tx
        status=IORD_ALTERA_AVALON_UART_STATUS(RS485_3_BASE);
    //set the tx reg
    IOWR_ALTERA_AVALON_UART_TXDATA(RS485_3_BASE,data);
//    usleep(400*1000);
}

//rs485 2 rx
int Rs485_2_receive(void)
{
    alt_u16 status;
    int temp;
    //read the state reg
    status=IORD_ALTERA_AVALON_UART_STATUS(RS485_2_BASE);
    while(!(status&0x0080))//wait until rx finished
        status=IORD_ALTERA_AVALON_UART_STATUS(RS485_2_BASE);
    //read the rx reg
    temp=IORD_ALTERA_AVALON_UART_RXDATA(RS485_2_BASE);
    return temp;
}

//rs485 3 rx
int Rs485_3_receive(void)
{
    alt_u16 status;
    int temp;
    //read the state reg
    status=IORD_ALTERA_AVALON_UART_STATUS(RS485_3_BASE);
    while(!(status&0x0080))//wait until rx finished
        status=IORD_ALTERA_AVALON_UART_STATUS(RS485_3_BASE);        
    //read the rx reg
    temp=IORD_ALTERA_AVALON_UART_RXDATA(RS485_3_BASE);
    return temp;
}

//rs485 3 ISR
void Rs485_3_ISR(void * context,alt_u32 id)
{
    int temp1;
    //read the rx reg
    temp1=IORD_ALTERA_AVALON_UART_RXDATA(RS485_3_BASE);
    RS485_2_3_leddata1=temp1;
    //clear the rx reg
    IOWR_ALTERA_AVALON_UART_RXDATA(RS485_3_BASE, 0x0);
    
    //clear the irq flag
    IOWR_ALTERA_AVALON_UART_STATUS(RS485_3_BASE, 0x0);
    
    //rx irq disable
    alt_irq_disable(RS485_3_IRQ);
    //Can0_init();
}

//rs485 3 initial
void Rs485_3_init()
{

    //rx irq enable
    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_3_BASE, 0x80);
    //clear the irq flag
    IOWR_ALTERA_AVALON_UART_STATUS(RS485_3_BASE, 0x0);
    //register the irq of can 1
    alt_irq_register(RS485_3_IRQ,0,Rs485_3_ISR);
    //enable the irq
    alt_irq_enable(RS485_3_IRQ);
    
}

int RS485_2_3_loopback( void )
{
    int senddata ; //the sending data

    const alt_u32 time_out0 = alt_ticks_per_second()*1;
    const alt_u32 time_out1 = alt_ticks_per_second()*2;    
    
    alt_u32 time_start;
    time_start = alt_nticks();
        
    //rs485 3 initial
    Rs485_3_init();
    //receiving data initial
    RS485_2_3_leddata0 = 0;
    RS485_2_3_leddata1 = 0;
    //read the switch value ,so you can set the senddata via the sw[7:0],if not set,default value 0x5a
    senddata = (IORD_ALTERA_AVALON_PIO_DATA(SW_BASE) >> 8) & 0x0ff;
    
    if(senddata==0)
    {
        senddata = 0x5a;
    }
    
    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_2_BASE, 0x7ff & (IORD_ALTERA_AVALON_UART_CONTROL(RS485_2_BASE))) ; //RTS enable
    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_3_BASE, 0x800 | (IORD_ALTERA_AVALON_UART_CONTROL(RS485_3_BASE))) ; //RTS Disable 
 
    while( (alt_nticks() - time_start) < time_out0 ){
        //rs485 2 tx
        Rs485_2_send(senddata);
    }//end while
 
     usleep(800*1000); //delay  
     
     //rs485 2 initial
     Rs485_2_init();

    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_2_BASE, 0x800 | (IORD_ALTERA_AVALON_UART_CONTROL(RS485_2_BASE))) ; //RTS Disable
    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_3_BASE, 0x7ff & (IORD_ALTERA_AVALON_UART_CONTROL(RS485_3_BASE))) ; //RTS enable
    
    while( (alt_nticks() - time_start) < time_out1 ){
        //rs485 3 tx
        Rs485_3_send(RS485_2_3_leddata1);
    }//end while 
    
    if((RS485_2_3_leddata1 == RS485_2_3_leddata0) &&(senddata == RS485_2_3_leddata0) )
    {
       printf("--------tx data: %x---------\n",senddata);
       printf("--------loopback data:%x---------\n",RS485_2_3_leddata0);
       //SEG7_Hex(senddata,0x30);
//       SEG7_SET(4, szMap[senddata & 0x0f]);
//       SEG7_SET(5, szMap[(senddata>>4) & 0x0f]);
//       SEG7_SET(6, 0x40);
//       SEG7_SET(7, 0x6D);
       
       return 1; 
    }
    else
    {
        //FAIL 
//        SEG7_SET(4, 0x38);
//        SEG7_SET(5, 6);
//        SEG7_SET(6, 119);
//        SEG7_SET(7, 113);
////        SEG7_SET(4, 0x0);
//        SEG7_SET(5, 0x0);
//        SEG7_SET(6, 0x0);
//        SEG7_SET(7, 0x0);
        return 0;
    }
    
    
}//end main

