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

volatile int RS485_0_1_leddata0;
volatile int RS485_0_1_leddata1;

/////////////////////////sub routine///////////////////////////////////
//rs485 0 ISR routine
void Rs485_0_ISR(void * context,alt_u32 id)
{
    int temp0;
    //read the rx reg
    temp0=IORD_ALTERA_AVALON_UART_RXDATA(RS485_0_BASE);
    RS485_0_1_leddata0=temp0;
    //clear the rx reg
    IOWR_ALTERA_AVALON_UART_RXDATA(RS485_0_BASE, 0x0);
    //clear the irq flag
    IOWR_ALTERA_AVALON_UART_STATUS(RS485_0_BASE, 0x0);  
    //rx irq disable
    alt_irq_disable(RS485_0_IRQ);
        
}

//rs485 0 initial routine
void Rs485_0_init()
{
    //register the irq of can 0
    alt_irq_register(RS485_0_IRQ,0,Rs485_0_ISR);
    //rx irq enable
    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_0_BASE, 0x80);
    //clear the irq flag
    IOWR_ALTERA_AVALON_UART_STATUS(RS485_0_BASE, 0x0); 
    //enable the irq
    alt_irq_enable(RS485_0_IRQ);
}
//rs485 0 send 1 byte data packet
void Rs485_0_send(unsigned char data)
{
    alt_u16 status;
    //read the state reg
    status=IORD_ALTERA_AVALON_UART_STATUS(RS485_0_BASE);
    while(!(status&0x0040)) //wait until finish tx
        status=IORD_ALTERA_AVALON_UART_STATUS(RS485_0_BASE);
    //set the tx reg
    IOWR_ALTERA_AVALON_UART_TXDATA(RS485_0_BASE,data);
}

//rs485 1 send 1 byte data packet
void Rs485_1_send(unsigned char data)
{
    alt_u16 status;
    //read the state reg
    status=IORD_ALTERA_AVALON_UART_STATUS(RS485_1_BASE);
    while(!(status&0x0040)) //wait until finish tx
        status=IORD_ALTERA_AVALON_UART_STATUS(RS485_1_BASE);
    //set the tx reg
    IOWR_ALTERA_AVALON_UART_TXDATA(RS485_1_BASE,data);

}

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

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

//rs485 1 rx ISR
void Rs485_1_ISR(void * context,alt_u32 id)
{
    int temp1;
    //read the rx reg
    temp1=IORD_ALTERA_AVALON_UART_RXDATA(RS485_1_BASE);
    RS485_0_1_leddata1=temp1;
    //clear the rx reg
    IOWR_ALTERA_AVALON_UART_RXDATA(RS485_1_BASE, 0x0);    
    //clear the irq flag
    IOWR_ALTERA_AVALON_UART_STATUS(RS485_1_BASE, 0x0);    
    //rx irq disable
    alt_irq_disable(RS485_1_IRQ);

}

//rs485 1 ISR initial
void Rs485_1_init()
{
    //rx irq enable
    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_1_BASE, 0x80);
    //clear the irq flag
    IOWR_ALTERA_AVALON_UART_STATUS(RS485_1_BASE, 0x0);
    //register the irq of rs485 1
    alt_irq_register(RS485_1_IRQ,0,Rs485_1_ISR);
    //enable the irq
    alt_irq_enable(RS485_1_IRQ);    

}

int RS485_0_1_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 1 initial for receiving
    Rs485_1_init();
    //initial the receiving data
    RS485_0_1_leddata0 = 0;
    RS485_0_1_leddata1 = 0;
    //read the switch value ,so you can set the senddata via the sw[7:0],if not set,the default value 0x5a
    senddata = (IORD_ALTERA_AVALON_PIO_DATA(SW_BASE)) & 0x0ff;    
    if(senddata==0)
    {
        senddata = 0x5a;
    }
    
    //rts control
    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_0_BASE, 0x7ff & (IORD_ALTERA_AVALON_UART_CONTROL(RS485_0_BASE))) ; //RTS enable
    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_1_BASE, 0x800 | (IORD_ALTERA_AVALON_UART_CONTROL(RS485_1_BASE))) ; //RTS Disable 
 
    while( (alt_nticks() - time_start) < time_out0 ){
        //rs485 0 tx
        Rs485_0_send(senddata);
    }//end while
         
     usleep(800*1000); //delay 
     
     //rs485 1 initial for receiving1
     Rs485_0_init();
    //rts control    
    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_1_BASE, 0x7ff & (IORD_ALTERA_AVALON_UART_CONTROL(RS485_1_BASE))) ; //RTS enable
    IOWR_ALTERA_AVALON_UART_CONTROL(RS485_0_BASE, 0x800 | (IORD_ALTERA_AVALON_UART_CONTROL(RS485_0_BASE))) ; //RTS Disable              
    while( (alt_nticks() - time_start) < time_out1 ){
      //rs485 1 send        
        Rs485_1_send(RS485_0_1_leddata1);
    }//end while    

    if((RS485_0_1_leddata1 == RS485_0_1_leddata0) &&(senddata == RS485_0_1_leddata0) )
    {
       printf("--------tx data:%x---------\n",senddata);
       printf("--------loopback data:%x---------\n",RS485_0_1_leddata0);
//       SEG7_Hex(senddata,0x03);
//       SEG7_SET(2, 0x40);
//       SEG7_SET(3, 0x6D);
//       SEG7_SET(4, 0x0);
//       SEG7_SET(5, 0x0);
//       SEG7_SET(6, 0x0);
//       SEG7_SET(7, 0x0);
//       
       return 1; 
    }
    else
    {
//        //FAIL 
//        SEG7_SET(0, 0x38);
//        SEG7_SET(1, 6);
//        SEG7_SET(2, 119);
//        SEG7_SET(3, 113);
//        SEG7_SET(4, 0x0);
//        SEG7_SET(5, 0x0);
//        SEG7_SET(6, 0x0);
//        SEG7_SET(7, 0x0);
        return 0;
    }
    
    
}//end main

