/*
 * Comm_Test.c
 *
 *  Created on: 2020�~4��20��
 *      Author: Wendell
 */

#include <stdio.h>
#include <stdlib.h>
#include "Comm_Test.h"
#include "IO_Test.h"
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <linux/wireless.h>
#include <unistd.h>                 //write, close, usleep, read
#include <string.h>

#include <fcntl.h>                  //uart
#include <termios.h>                //uart

int Can0Fd, Can1Fd, LcmPort, RfidPort, InternalCommPort;
char *LcmPortName = "/dev/ttyS3";
char *RfidPortName = "/dev/ttyS2";
char *InternalCommPortName = "/dev/ttyS5";

//================================================
// initial can-bus 0
//================================================
int InitCan0Bus()
{
    int                     s0,nbytes;
    struct timeval          tv;
    struct ifreq            ifr0;
    struct sockaddr_can     addr0;

    system("/sbin/ip link set can0 down");
    system("/sbin/ip link set can0 type can bitrate 500000 restart-ms 100");
    system("/sbin/ip link set can0 up");

    s0 = socket(PF_CAN, SOCK_RAW, CAN_RAW);

    tv.tv_sec = 0;
    tv.tv_usec = 10000;
    if (setsockopt(s0, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct  timeval)) < 0)
    {
        #ifdef SystemLogMessage
        DEBUG_ERROR("Set SO_RCVTIMEO NG");
        #endif
    }
    nbytes = 40960;
    if (setsockopt(s0, SOL_SOCKET,  SO_RCVBUF, &nbytes, sizeof(int)) < 0)
    {
        #ifdef SystemLogMessage
        DEBUG_ERROR("Set SO_RCVBUF NG");
        #endif
    }
    nbytes = 40960;
    if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0)
    {
        #ifdef SystemLogMessage
        DEBUG_ERROR("Set SO_SNDBUF NG");
        #endif
    }

    strcpy(ifr0.ifr_name, "can0" );
    ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
    addr0.can_family = AF_CAN;
    addr0.can_ifindex = ifr0.ifr_ifindex;
    bind(s0, (struct sockaddr *)&addr0, sizeof(addr0));
    return s0;
}


//================================================
// initial can-bus 1
//================================================
int InitCan1Bus()
{
    int                     s0,nbytes;
    struct timeval          tv;
    struct ifreq            ifr0;
    struct sockaddr_can     addr0;

    system("/sbin/ip link set can1 down");
    system("/sbin/ip link set can1 type can bitrate 500000 restart-ms 100");
    system("/sbin/ip link set can1 up");

    s0 = socket(PF_CAN, SOCK_RAW, CAN_RAW);

    tv.tv_sec = 0;
    tv.tv_usec = 10000;
    if (setsockopt(s0, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct  timeval)) < 0)
    {
        #ifdef SystemLogMessage
        PRINTF_LIB_FUNC("Set SO_RCVTIMEO NG");
        #endif
    }
    nbytes = 40960;
    if (setsockopt(s0, SOL_SOCKET,  SO_RCVBUF, &nbytes, sizeof(int)) < 0)
    {
        #ifdef SystemLogMessage
        PRINTF_LIB_FUNC("Set SO_RCVBUF NG");
        #endif
    }
    nbytes = 40960;
    if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0)
    {
        #ifdef SystemLogMessage
        PRINTF_LIB_FUNC("Set SO_SNDBUF NG");
        #endif
    }

    strcpy(ifr0.ifr_name, "can1" );
    ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
    addr0.can_family = AF_CAN;
    addr0.can_ifindex = ifr0.ifr_ifindex;
    bind(s0, (struct sockaddr *)&addr0, sizeof(addr0));
    return s0;
}

void SendCan0Frame(int cmd, unsigned char *data, unsigned char dataLen)
{
    struct can_frame frame;

    frame.can_id = cmd;
    frame.can_dlc = dataLen;
    memcpy(frame.data, data, sizeof(frame.data));

    write(Can0Fd, &frame, sizeof(struct can_frame));
}

void SendCan1Frame(int cmd, unsigned char *data, unsigned char dataLen)
{
    struct can_frame frame;

    frame.can_id = cmd;
    frame.can_dlc = dataLen;
    memcpy(frame.data, data, sizeof(frame.data));

    write(Can1Fd, &frame, sizeof(struct can_frame));
}

void Can0TxMessageTest(void)
{
    int id = 0x80123456;
    unsigned char data[8];

    data[0] = 0x55;
    data[1] = 0xAA;

    SendCan0Frame(id, data, 2);
}

void Can1TxMessageTest(void)
{
    int id = 0x80654321;
    unsigned char data[8];

    data[0] = 0xAA;
    data[1] = 0x55;

    SendCan1Frame(id, data, 2);
}

//==========================================
// Open LCM Port
//==========================================
int OpenLcmPort()
{
    int fd;
    struct termios tios;

    fd = open(LcmPortName, O_RDWR);
    if (fd <= 0)
    {
        #ifdef SystemLogMessage
        DEBUG_ERROR("open /dev/ttyS3 NG \n");
        #endif
        return -1;
    }
    ioctl(fd, TCGETS, &tios);
    tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
    tios.c_lflag = 0;
    tios.c_iflag = 0;
    tios.c_oflag = 0;
    tios.c_cc[VMIN] = 0;
    tios.c_cc[VTIME] = (unsigned char) 5;
    tios.c_lflag = 0;
    tcflush(fd, TCIFLUSH);
    ioctl(fd, TCSETS, &tios);

    return fd;
}

void CloseLcmPort()
{
    close(LcmPort);
}

//==========================================
// Open RFID Port
//==========================================
int OpenRfidPort()
{
    int fd;
    struct termios tios;

    fd = open(RfidPortName, O_RDWR);
    if (fd <= 0)
    {
        #ifdef SystemLogMessage
        DEBUG_ERROR("open /dev/ttyS2 NG \n");
        #endif
        return -1;
    }
    ioctl(fd, TCGETS, &tios);
    tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
    tios.c_lflag = 0;
    tios.c_iflag = 0;
    tios.c_oflag = 0;
    tios.c_cc[VMIN] = 0;
    tios.c_cc[VTIME] = (unsigned char) 5;
    tios.c_lflag = 0;
    tcflush(fd, TCIFLUSH);
    ioctl(fd, TCSETS, &tios);

    return fd;
}

void CloseRfidPort()
{
    close(RfidPort);
}

void InitRS485DirectionIO(void)
{
    //LCD_AC_BIAS_EN    =>  GPIO2_25*//*RS-485 for module DE control
    gpio_set_direction(PIN_AM_DE_1, GPIO_DIR_OUTPUT);
    gpio_write(PIN_AM_DE_1, 1);
    //system("echo 89 > /sys/class/gpio/export");
    //system("echo \"out\" > /sys/class/gpio/gpio89/direction");
    //system("echo 1 > /sys/class/gpio/gpio89/value");

    //LCD_HSYNC     =>  GPIO2_23*//*RS-485 for module RE control
    gpio_set_direction(PIN_AM_RE_1, GPIO_DIR_OUTPUT);
    gpio_write(PIN_AM_RE_1, 0);
    //system("echo 87 > /sys/class/gpio/export");
    //system("echo \"out\" > /sys/class/gpio/gpio87/direction");
    //system("echo 0 > /sys/class/gpio/gpio87/value");
}

//==========================================
// Open Internal Comm Port
//==========================================
int OpenInternalCommPort()
{
    int fd;
    struct termios tios;

    fd = open(InternalCommPortName, O_RDWR);
    if (fd <= 0)
    {
        #ifdef SystemLogMessage
        DEBUG_ERROR("open /dev/ttyS5 NG \n");
        #endif
        return -1;
    }
    ioctl(fd, TCGETS, &tios);
    tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
    tios.c_lflag = 0;
    tios.c_iflag = 0;
    tios.c_oflag = 0;
    tios.c_cc[VMIN] = 0;
    tios.c_cc[VTIME] = (unsigned char) 5;
    tios.c_lflag = 0;
    tcflush(fd, TCIFLUSH);
    ioctl(fd, TCSETS, &tios);

    return fd;
}

void CloseInternalCommPort()
{
    close(InternalCommPort);
}

void DoDCMCommTest(void)
{
    struct can_frame frame;
    int rxByte = 0;
    unsigned char uartTx[2], uartRx[2];

    Can0Fd = InitCan0Bus();
    Can1Fd = InitCan1Bus();
    LcmPort = OpenLcmPort();
    RfidPort = OpenRfidPort();

    InitRS485DirectionIO();
    InternalCommPort = OpenInternalCommPort();

    if(Can0Fd < 0)
    {
        printf("\r\nInit Can Bus 0 fail");
        return;
    }

    if(Can1Fd < 0)
    {
        printf("\r\nInit Can Bus 1 fail");
        return;
    }

    if(LcmPort < 0)
    {
        printf("\r\nInit LCM Port fail");
        return;
    }

    if(RfidPort < 0)
    {
        printf("\r\nInit RFID Port fail");
        return;
    }

    if(InternalCommPort < 0)
    {
        printf("\r\nInit Internal Comm Port fail");
        return;
    }

    //*************************CAN Bus Test*************************
    Can0TxMessageTest();
    Can1TxMessageTest();

    //usleep(10000);

    rxByte = read(Can1Fd, &frame, sizeof(struct can_frame));

    if(rxByte > 0 && frame.can_id == 0x80123456 && frame.data[0] == 0x55 && frame.data[1] == 0xAA)
    {
        printf("\r\nCan Bus 0 Tx OK");
    }
    else
    {
        printf("\r\nCan Bus 0 Tx Fail");
        return;
    }

    rxByte = read(Can0Fd, &frame, sizeof(struct can_frame));

    if(rxByte > 0 && frame.can_id == 0x80654321 && frame.data[0] == 0xAA && frame.data[1] == 0x55)
    {
        printf("\r\nCan Bus 1 Tx OK");
    }
    else
    {
        printf("\r\nCan Bus 1 Tx Fail");
        return;
    }

    //*************************LCM UART Test*************************
    uartTx[0] = 0x55;
    uartTx[1] = 0xAA;

    write(LcmPort, uartTx, 2);
    rxByte = read(LcmPort, uartRx, 2);
    CloseLcmPort();

    if(rxByte == 2 && uartRx[0] == 0x55 && uartRx[1] == 0xAA)
    {
        printf("\r\nLCM Port Test OK");
    }
    else
    {
        printf("\r\nLCM Port Test Fail");
        return;
    }

    //*************************RFID UART Test*************************
    uartTx[0] = 0xAA;
    uartTx[1] = 0x55;

    write(RfidPort, uartTx, 2);
    rxByte = read(RfidPort, uartRx, 2);
    CloseRfidPort();

    if(rxByte == 2 && uartRx[0] == 0xAA && uartRx[1] == 0x55)
    {
        printf("\r\nRFID Port Test OK");
    }
    else
    {
        printf("\r\nRFID Port Test Fail");
        return;
    }

    //*************************Internal Comm RS485 Test*************************
    uartTx[0] = 0x5A;
    uartTx[1] = 0x5A;
    write(InternalCommPort, uartTx, 2);
    rxByte = read(InternalCommPort, uartRx, 2);
    CloseInternalCommPort();

    if(rxByte == 2 && uartRx[0] == 0x5A && uartRx[1] == 0x5A)
    {
        printf("\r\nInternal Comm Port Test OK");
    }
    else
    {
        printf("\r\nInternal Comm Port Test Fail");
        return;
    }

    printf("\r\nComm Test Done!");
    printf("\r\nSuccess!\r\n");

}