rework i2cbus checkbusy, MPSSE single read is too slow, use multiple read

This commit is contained in:
lancos 2019-08-13 01:11:36 +02:00
parent 58102a203d
commit b10e098137
5 changed files with 219 additions and 27 deletions

View File

@ -146,6 +146,39 @@ class BusInterface
virtual int IsClockDataUP() = 0;
virtual int IsClockDataDOWN() = 0;
virtual bool CheckDataLines(int len = 1, int sda = -1, int scl = -1)
{
bool test = false;
if (len > 0)
{
do {
if (sda == 0 && scl == 0)
test = IsClockDataDOWN();
else if (sda > 0 && scl > 0)
test = IsClockDataUP();
else
{
bool test_sda = true, test_scl = true;
if (sda > 0)
test_sda = GetDataIn();
else if (sda == 0)
test_sda = !GetDataIn();
if (scl > 0)
test_scl = GetClock();
else if (scl == 0)
test_scl = !GetClock();
test = (test_sda && test_scl);
}
} while (test && --len > 0);
}
return test;
}
int GetCmd2CmdDelay() const
{
return cmd2cmd_delay;

View File

@ -454,7 +454,7 @@ void e2App::SetInterfaceType(HInterfaceType type)
busIntp = &ponyprog_ftI;
ponyprog_ftI.SetUSBVid(0x0403);
ponyprog_ftI.SetUSBPid(0x6e38);
ponyprog_ftI.ConfigPins(3, 2, 1, 0, 4, 5, 7);
ponyprog_ftI.ConfigPins(3, 2, 1, 0, /* 4 */ -1, 5, 7);
break;
case SIPROG_API:

View File

@ -52,14 +52,10 @@ I2CBus::~I2CBus()
int I2CBus::CheckBusy()
{
register int count;
for (count = BUSYDELAY; count > 0 && isSCLSDAuno(); count--)
{
WaitUsec(1);
}
return (count ? IICERR_BUSBUSY : OK);
if (busI->CheckDataLines(BUSYDELAY, 1, 1))
return OK;
else
return IICERR_BUSBUSY;
}
/** I2CBus specification **

View File

@ -298,7 +298,7 @@ int MpsseInterface::Open(int port)
{
ctx.reset();
//ctx.flush();
ctx.set_read_chunk_size(64);
ctx.set_read_chunk_size(256);
ctx.set_write_chunk_size(1024);
//ctx.set_event_char();
//ctx.set_error_char();
@ -477,6 +477,84 @@ int MpsseInterface::GetPins()
return ret;
}
int MpsseInterface::GetLowPinsMulti(int bufsiz, uint8_t *buf, int len)
{
if (len > bufsiz)
len = bufsiz;
if (cmdbuf.almostFull(len))
{
Flush();
}
for (int k = 0; k < len; k++)
cmdbuf.append(GET_BITS_LOW);
cmdbuf.append(SEND_IMMEDIATE);
int ret = Flush();
if (ret == OK)
{
int timeout = 10000;
do
{
ret = ctx.read(buf, len);
if (ret < 0)
{
qWarning() << __PRETTY_FUNCTION__ << "read failed:" << ctx.error_string();
return -1;
}
}
while (ret == 0 && --timeout > 0);
if (timeout == 0)
{
ret = E2P_TIMEOUT;
}
}
return ret;
}
bool MpsseInterface::CheckDataLines(int len, int sda, int scl)
{
uint8_t buf[512];
bool test = false;
Q_ASSERT(len > 0);
Q_ASSERT(len <= (int)sizeof(buf));
if (GetLowPinsMulti(sizeof(buf), buf, len) == len)
{
test = true;
for (int k = 0; test && k < len; k++)
{
if (sda == 0 && scl == 0)
test = IsClockDataDOWN(buf[k]);
else if (sda > 0 && scl > 0)
test = IsClockDataUP(buf[k]);
else
{
bool test_sda = true, test_scl = true;
if (sda > 0)
test_sda = GetDataIn(buf[k]);
else if (sda == 0)
test_sda = !GetDataIn(buf[k]);
if (scl > 0)
test_scl = GetClock(buf[k]);
else if (scl == 0)
test_scl = !GetClock(buf[k]);
test = (test_sda && test_scl);
}
} while (test && --len > 0);
}
return test;
}
int MpsseInterface::xferBit(int &err, int b, int mode)
{
int cmd = MPSSE_BITMODE;
@ -828,6 +906,20 @@ void MpsseInterface::ClearClockData()
}
}
int MpsseInterface::GetDataIn(int val)
{
val = (val & pin_datain) ? 1 : 0;
if (cmdWin->GetPolarity() & DININV)
{
return !val;
}
else
{
return val;
}
}
int MpsseInterface::GetDataIn()
{
if (IsInstalled())
@ -840,17 +932,7 @@ int MpsseInterface::GetDataIn()
}
else
{
//qDebug() << __PRETTY_FUNCTION__ << "=" << val;
val = (val & pin_datain) ? 1 : 0;
if (cmdWin->GetPolarity() & DININV)
{
return !val;
}
else
{
return val;
}
return GetDataIn(val);
}
}
else
@ -859,23 +941,98 @@ int MpsseInterface::GetDataIn()
}
}
int MpsseInterface::GetClock(int val)
{
if (pin_clockin == 0)
return 1;
else
return (val & pin_clockin) ? 1 : 0;
}
int MpsseInterface::GetClock()
{
return 1;
if (pin_clockin == 0)
{
return 1;
}
else
{
if (IsInstalled())
{
int val = GetPins();
if (val < 0)
{
qWarning() << __PRETTY_FUNCTION__ << "read failed.";
return val;
}
else
{
return GetClock(val);
}
}
else
{
return E2ERR_NOTINSTALLED;
}
}
}
int MpsseInterface::IsClockDataUP(int val)
{
if (pin_clockin == 0)
return GetDataIn(val);
else
return (GetClock(val) && GetDataIn(val));
}
int MpsseInterface::IsClockDataUP()
{
//qDebug() << __PRETTY_FUNCTION__ << "*** Inst=" << IsInstalled();
if (IsInstalled())
{
int val = GetPins();
if (val < 0)
{
qWarning() << __PRETTY_FUNCTION__ << "read failed.";
return val;
}
else
{
return IsClockDataUP(val);
}
}
else
{
return E2ERR_NOTINSTALLED;
}
}
return GetDataIn();
int MpsseInterface::IsClockDataDOWN(int val)
{
if (pin_clockin == 0)
return !GetDataIn(val);
else
return (!GetClock(val) && !GetDataIn(val));
}
int MpsseInterface::IsClockDataDOWN()
{
//qDebug() << __PRETTY_FUNCTION__ << "*** Inst=" << IsInstalled();
return !GetDataIn();
if (IsInstalled())
{
int val = GetPins();
if (val < 0)
{
qWarning() << __PRETTY_FUNCTION__ << "read failed.";
return val;
}
else
{
return IsClockDataDOWN(val);
}
}
else
{
return E2ERR_NOTINSTALLED;
}
}
/**

View File

@ -98,11 +98,16 @@ class MpsseInterface : public BusInterface
virtual void SetDataOut(int sda = 1);
virtual void SetClock(int scl = 1);
virtual int GetDataIn();
virtual int GetDataIn(int val);
virtual int GetClock();
virtual int GetClock(int val);
virtual void SetClockData();
virtual void ClearClockData();
virtual int IsClockDataUP(int val);
virtual int IsClockDataUP();
virtual int IsClockDataDOWN(int val);
virtual int IsClockDataDOWN();
virtual bool CheckDataLines(int len = 1, int sda = -1, int scl = -1);
//virtual int TestPort(int port);
@ -131,6 +136,7 @@ class MpsseInterface : public BusInterface
int SetFrequency(uint32_t freq);
int SendPins(int new_data, int new_directions = -1);
int GetPins();
int GetLowPinsMulti(int bufsiz, uint8_t *buf, int len);
//utility to set/reset/toggle a pin
unsigned int OutDataMask(int old_val, int mask, int val)