#include "oshw.h"
#include "osal.h"
#include "ethercattype.h"
#include "ethercatbase.h"
#include "ethercatmain.h"
#include "ethercatdc.h"
#define PORTM0 0x01
#define PORTM1 0x02
#define PORTM2 0x04
#define PORTM3 0x08
#define SyncDelay ((int32)100000000)
void ecx_dcsync0(ecx_contextt *context, uint16 slave, boolean act, uint32 CyclTime, int32 CyclShift)
{
uint8 h, RA;
uint16 slaveh;
int64 t, t1;
int32 tc;
slaveh = context->slavelist[slave].configadr;
RA = 0;
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCSYNCACT, sizeof(RA), &RA, EC_TIMEOUTRET);
if (act)
{
RA = 1 + 2;
}
h = 0;
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCCUC, sizeof(h), &h, EC_TIMEOUTRET);
t1 = 0;
(void)ecx_FPRD(context->port, slaveh, ECT_REG_DCSYSTIME, sizeof(t1), &t1, EC_TIMEOUTRET);
t1 = etohll(t1);
if (CyclTime > 0)
{
t = ((t1 + SyncDelay) / CyclTime) * CyclTime + CyclTime + CyclShift;
}
else
{
t = t1 + SyncDelay + CyclShift;
}
t = htoell(t);
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCSTART0, sizeof(t), &t, EC_TIMEOUTRET);
tc = htoel(CyclTime);
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCCYCLE0, sizeof(tc), &tc, EC_TIMEOUTRET);
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCSYNCACT, sizeof(RA), &RA, EC_TIMEOUTRET);
context->slavelist[slave].DCactive = (uint8)act;
context->slavelist[slave].DCshift = CyclShift;
context->slavelist[slave].DCcycle = CyclTime;
}
void ecx_dcsync01(ecx_contextt *context, uint16 slave, boolean act, uint32 CyclTime0, uint32 CyclTime1, int32 CyclShift)
{
uint8 h, RA;
uint16 slaveh;
int64 t, t1;
int32 tc;
uint32 TrueCyclTime;
TrueCyclTime = ((CyclTime1 / CyclTime0) + 1) * CyclTime0;
slaveh = context->slavelist[slave].configadr;
RA = 0;
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCSYNCACT, sizeof(RA), &RA, EC_TIMEOUTRET);
if (act)
{
RA = 1 + 2 + 4;
}
h = 0;
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCCUC, sizeof(h), &h, EC_TIMEOUTRET);
t1 = 0;
(void)ecx_FPRD(context->port, slaveh, ECT_REG_DCSYSTIME, sizeof(t1), &t1, EC_TIMEOUTRET);
t1 = etohll(t1);
if (CyclTime0 > 0)
{
t = ((t1 + SyncDelay) / TrueCyclTime) * TrueCyclTime + TrueCyclTime + CyclShift;
}
else
{
t = t1 + SyncDelay + CyclShift;
}
t = htoell(t);
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCSTART0, sizeof(t), &t, EC_TIMEOUTRET);
tc = htoel(CyclTime0);
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCCYCLE0, sizeof(tc), &tc, EC_TIMEOUTRET);
tc = htoel(CyclTime1);
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCCYCLE1, sizeof(tc), &tc, EC_TIMEOUTRET);
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCSYNCACT, sizeof(RA), &RA, EC_TIMEOUTRET);
context->slavelist[slave].DCactive = (uint8)act;
context->slavelist[slave].DCshift = CyclShift;
context->slavelist[slave].DCcycle = CyclTime0;
}
static int32 ecx_porttime(ecx_contextt *context, uint16 slave, uint8 port)
{
int32 ts;
switch (port)
{
case 0:
ts = context->slavelist[slave].DCrtA;
break;
case 1:
ts = context->slavelist[slave].DCrtB;
break;
case 2:
ts = context->slavelist[slave].DCrtC;
break;
case 3:
ts = context->slavelist[slave].DCrtD;
break;
default:
ts = 0;
break;
}
return ts;
}
static uint8 ecx_prevport(ecx_contextt *context, uint16 slave, uint8 port)
{
uint8 pport = port;
uint8 aport = context->slavelist[slave].activeports;
switch(port)
{
case 0:
if(aport & PORTM2)
pport = 2;
else if (aport & PORTM1)
pport = 1;
else if (aport & PORTM3)
pport = 3;
break;
case 1:
if(aport & PORTM3)
pport = 3;
else if (aport & PORTM0)
pport = 0;
else if (aport & PORTM2)
pport = 2;
break;
case 2:
if(aport & PORTM1)
pport = 1;
else if (aport & PORTM3)
pport = 3;
else if (aport & PORTM0)
pport = 0;
break;
case 3:
if(aport & PORTM0)
pport = 0;
else if (aport & PORTM2)
pport = 2;
else if (aport & PORTM1)
pport = 1;
break;
}
return pport;
}
static uint8 ecx_parentport(ecx_contextt *context, uint16 parent)
{
uint8 parentport = 0;
uint8 b;
b = context->slavelist[parent].consumedports;
if (b & PORTM3)
{
parentport = 3;
b &= (uint8)~PORTM3;
}
else if (b & PORTM1)
{
parentport = 1;
b &= (uint8)~PORTM1;
}
else if (b & PORTM2)
{
parentport = 2;
b &= (uint8)~PORTM2;
}
else if (b & PORTM0)
{
parentport = 0;
b &= (uint8)~PORTM0;
}
context->slavelist[parent].consumedports = b;
return parentport;
}
boolean ecx_configdc(ecx_contextt *context)
{
uint16 i, slaveh, parent, child;
uint16 parenthold = 0;
uint16 prevDCslave = 0;
int32 ht, dt1, dt2, dt3;
int64 hrt;
uint8 entryport;
int8 nlist;
int8 plist[4];
int32 tlist[4];
ec_timet mastertime;
uint64 mastertime64;
context->slavelist[0].hasdc = FALSE;
context->grouplist[0].hasdc = FALSE;
ht = 0;
ecx_BWR(context->port, 0, ECT_REG_DCTIME0, sizeof(ht), &ht, EC_TIMEOUTRET);
mastertime = osal_current_time();
mastertime.sec -= 946684800UL;
mastertime64 = (((uint64)mastertime.sec * 1000000) + (uint64)mastertime.usec) * 1000;
for (i = 1; i <= *(context->slavecount); i++)
{
context->slavelist[i].consumedports = context->slavelist[i].activeports;
if (context->slavelist[i].hasdc)
{
if (!context->slavelist[0].hasdc)
{
context->slavelist[0].hasdc = TRUE;
context->slavelist[0].DCnext = i;
context->slavelist[i].DCprevious = 0;
context->grouplist[context->slavelist[i].group].hasdc = TRUE;
context->grouplist[context->slavelist[i].group].DCnext = i;
}
else
{
context->slavelist[prevDCslave].DCnext = i;
context->slavelist[i].DCprevious = prevDCslave;
}
parenthold = 0;
prevDCslave = i;
slaveh = context->slavelist[i].configadr;
(void)ecx_FPRD(context->port, slaveh, ECT_REG_DCTIME0, sizeof(ht), &ht, EC_TIMEOUTRET);
context->slavelist[i].DCrtA = etohl(ht);
(void)ecx_FPRD(context->port, slaveh, ECT_REG_DCSOF, sizeof(hrt), &hrt, EC_TIMEOUTRET);
hrt = htoell(-etohll(hrt) + mastertime64);
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCSYSOFFSET, sizeof(hrt), &hrt, EC_TIMEOUTRET);
(void)ecx_FPRD(context->port, slaveh, ECT_REG_DCTIME1, sizeof(ht), &ht, EC_TIMEOUTRET);
context->slavelist[i].DCrtB = etohl(ht);
(void)ecx_FPRD(context->port, slaveh, ECT_REG_DCTIME2, sizeof(ht), &ht, EC_TIMEOUTRET);
context->slavelist[i].DCrtC = etohl(ht);
(void)ecx_FPRD(context->port, slaveh, ECT_REG_DCTIME3, sizeof(ht), &ht, EC_TIMEOUTRET);
context->slavelist[i].DCrtD = etohl(ht);
nlist = 0;
if (context->slavelist[i].activeports & PORTM0)
{
plist[nlist] = 0;
tlist[nlist] = context->slavelist[i].DCrtA;
nlist++;
}
if (context->slavelist[i].activeports & PORTM3)
{
plist[nlist] = 3;
tlist[nlist] = context->slavelist[i].DCrtD;
nlist++;
}
if (context->slavelist[i].activeports & PORTM1)
{
plist[nlist] = 1;
tlist[nlist] = context->slavelist[i].DCrtB;
nlist++;
}
if (context->slavelist[i].activeports & PORTM2)
{
plist[nlist] = 2;
tlist[nlist] = context->slavelist[i].DCrtC;
nlist++;
}
entryport = 0;
if((nlist > 1) && (tlist[1] < tlist[entryport]))
{
entryport = 1;
}
if((nlist > 2) && (tlist[2] < tlist[entryport]))
{
entryport = 2;
}
if((nlist > 3) && (tlist[3] < tlist[entryport]))
{
entryport = 3;
}
entryport = plist[entryport];
context->slavelist[i].entryport = entryport;
context->slavelist[i].consumedports &= (uint8)~(1 << entryport);
parent = i;
do
{
child = parent;
parent = context->slavelist[parent].parent;
}
while (!((parent == 0) || (context->slavelist[parent].hasdc)));
if (parent > 0)
{
context->slavelist[i].parentport = ecx_parentport(context, parent);
if (context->slavelist[parent].topology == 1)
{
context->slavelist[i].parentport = context->slavelist[parent].entryport;
}
dt1 = 0;
dt2 = 0;
dt3 = ecx_porttime(context, parent, context->slavelist[i].parentport) -
ecx_porttime(context, parent,
ecx_prevport(context, parent, context->slavelist[i].parentport));
if (context->slavelist[i].topology > 1)
{
dt1 = ecx_porttime(context, i,
ecx_prevport(context, i, context->slavelist[i].entryport)) -
ecx_porttime(context, i, context->slavelist[i].entryport);
}
if (dt1 > dt3) dt1 = -dt1;
if ((child - parent) > 1)
{
dt2 = ecx_porttime(context, parent,
ecx_prevport(context, parent, context->slavelist[i].parentport)) -
ecx_porttime(context, parent, context->slavelist[parent].entryport);
}
if (dt2 < 0) dt2 = -dt2;
context->slavelist[i].pdelay = ((dt3 - dt1) / 2) + dt2 +
context->slavelist[parent].pdelay;
ht = htoel(context->slavelist[i].pdelay);
(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCSYSDELAY, sizeof(ht), &ht, EC_TIMEOUTRET);
}
}
else
{
context->slavelist[i].DCrtA = 0;
context->slavelist[i].DCrtB = 0;
context->slavelist[i].DCrtC = 0;
context->slavelist[i].DCrtD = 0;
parent = context->slavelist[i].parent;
if ( (parent > 0) && (context->slavelist[parent].topology > 2))
parenthold = parent;
if ( parenthold && (context->slavelist[i].topology == 1))
{
ecx_parentport(context, parenthold);
parenthold = 0;
}
}
}
return context->slavelist[0].hasdc;
}
#ifdef EC_VER1
void ec_dcsync0(uint16 slave, boolean act, uint32 CyclTime, int32 CyclShift)
{
ecx_dcsync0(&ecx_context, slave, act, CyclTime, CyclShift);
}
void ec_dcsync01(uint16 slave, boolean act, uint32 CyclTime0, uint32 CyclTime1, int32 CyclShift)
{
ecx_dcsync01(&ecx_context, slave, act, CyclTime0, CyclTime1, CyclShift);
}
boolean ec_configdc(void)
{
return ecx_configdc(&ecx_context);
}
#endif