//
// Created by zx on 2019/8/19.
//

#include "CP16Card.h"
#include <stdio.h>
#include <string.h>
#include <pniobase.h>

bool CP16Card::m_quit=false;
device_data_t CP16Card::m_write_data=device_data_t();
device_data_t CP16Card::m_read_data=device_data_t();
Semaphore     g_read_signal;
Semaphore     g_write_signal;
CP16Card::CP16Card()
{}
CP16Card::~CP16Card()
{}



bool CP16Card::Init()
{
    static PNIOD_CBF_FUNCTIONS callbacks;
    memset(&callbacks,0,sizeof(callbacks));
    callbacks.size = sizeof(callbacks);
    callbacks.cbf_data_write = PNIO_cbf_data_write;
    callbacks.cbf_data_read = PNIO_cbf_data_read;

    m_write_data.api = 0;
    m_write_data.InDatLength = 4; /* convert device-view to controller-view */
    m_write_data.OutDatLength = 0; /* convert device-view to controller-view */
    m_write_data.OutData = 0;
    m_write_data.OutDatIocs = PNIO_S_BAD;
    m_write_data.OutDatIops = PNIO_S_BAD;
    m_write_data.InData = (PNIO_UINT8*)malloc(sizeof(PNIO_UINT8) * 4);
    m_write_data.InDatIops = PNIO_S_BAD;
    m_write_data.InDatIocs = PNIO_S_BAD;


    m_read_data.api = 0;
    m_read_data.InDatLength = 0; /* convert device-view to controller-view */
    m_read_data.OutDatLength = 4; /* convert device-view to controller-view */
    m_read_data.OutData = (PNIO_UINT8*)malloc(sizeof(PNIO_UINT8) * 4);
    m_read_data.OutDatIocs = PNIO_S_BAD;
    m_read_data.OutDatIops = PNIO_S_BAD;
    m_read_data.InData = 0;
    m_read_data.InDatIops = PNIO_S_BAD;
    m_read_data.InDatIocs = PNIO_S_BAD;


    InitCard(&callbacks);
    //开启线程，读取数据

}

bool CP16Card::UnInit()
{
    UnInitCard();
    return true;
}


float reserveByte(float data)
{
    int size=sizeof(float);
    float ret;
    char* p=(char*)&ret;
    char* p2=(char*)&data;
    for(int i=0;i<size;++i)
        p[size-1-i]=p2[i];
    return ret;
}


float CP16Card::ReadData(PNIO_UINT32 submodel)
{
    static PNIO_DEV_ADDR addr;
    addr.AddrType=PNIO_ADDR_GEO;
    addr.IODataType=PNIO_IO_IN_OUT;
    addr.u.Addr=0;
    addr.u.Geo.Slot=1;
    addr.u.Geo.Subslot=submodel;
    Trigger_data_read(&addr);
    g_read_signal.Wait();

    float ret=0;
    memcpy(&ret,m_read_data.OutData,sizeof(float));
    float data=reserveByte(ret);
    return data;

}

void CP16Card::WriteData(PNIO_UINT32 submodel, float data)
{
    static PNIO_DEV_ADDR addr;
    addr.AddrType=PNIO_ADDR_GEO;
    addr.IODataType=PNIO_IO_IN_OUT;
    addr.u.Addr=0;
    addr.u.Geo.Slot=1;
    addr.u.Geo.Subslot=submodel;

    float wd=reserveByte(data);
    memcpy(m_write_data.InData,&wd,sizeof(float));
    Trigger_data_write(&addr);
    g_write_signal.Wait();


}

PNIO_IOXS CP16Card::PNIO_cbf_data_read(PNIO_UINT32 DevHndl,
                                       PNIO_DEV_ADDR *pAddr,
                                       PNIO_UINT32 BufLen,
                                       PNIO_UINT8 *pBuffer,
                                       PNIO_IOXS Iops)
{
    if (BufLen == 0)
    {
        printf(" BufLen = 0, nothing to read..\n");
        m_read_data.OutDatIocs = PNIO_S_GOOD;
    }
    else if (BufLen <= (PNIO_UINT32)m_read_data.OutDatLength)
    {
        memset(m_read_data.OutData, 0, m_read_data.OutDatLength);
        memcpy(m_read_data.OutData, pBuffer, BufLen);  /*Copy the data from the stack to the application buffer*/
        m_read_data.OutDatIocs = PNIO_S_GOOD; /* assume everything is ok */

        //printf("  read data length %d  submodel %d  data : <----- \n",BufLen,pAddr->u.Geo.Subslot);
    }
    else
    {
        printf("NEW PNIO_cbf_data_read: Buflen=%lu > allowed size (%u)!!! Abort reading...  IOCS=  BAD !!! \n",
               (unsigned long)BufLen, m_read_data.OutDatLength);
    }
    g_read_signal.Signal();
    return (m_read_data.OutDatIocs); /* consumer state (of local IO device) */
}

PNIO_IOXS CP16Card::PNIO_cbf_data_write(PNIO_UINT32 DevHndl,
                                        PNIO_DEV_ADDR *pAddr,
                                        PNIO_UINT32 BufLen,
                                        PNIO_UINT8 *pBuffer,
                                        PNIO_IOXS Iocs)
{

    m_write_data.InDatIocs = Iocs;
    m_write_data.InDatIops = PNIO_S_BAD;
    if (BufLen == 0)
    {
        m_write_data.InDatIops = PNIO_S_GOOD;
    }
    else if (BufLen <= (PNIO_UINT32)m_write_data.InDatLength)
    {
        memcpy(pBuffer, m_write_data.InData, BufLen);
        m_write_data.InDatIops = PNIO_S_GOOD;

    }
    else
    {
        printf("!!! PNIO_cbf_data_write: Buflen=%lu > allowed size (%u)!!! Abort writing..\n",
               (unsigned long)BufLen, m_write_data.InDatLength);
    }
    g_write_signal.Signal();
    return m_write_data.InDatIops;
}
