2018-07-24 00:21:21 +01:00
|
|
|
#include "i2cdecoder.h"
|
|
|
|
|
2018-08-08 00:19:30 +01:00
|
|
|
using namespace i2c;
|
|
|
|
|
2018-08-14 08:40:55 +01:00
|
|
|
static const uint32_t kClockMultiplier = 10;
|
|
|
|
|
|
|
|
i2cDecoder::i2cDecoder(isoBuffer* sda_in, isoBuffer* scl_in, uint32_t clockRate) :
|
|
|
|
QObject(nullptr),
|
|
|
|
sda(sda_in),
|
|
|
|
scl(scl_in)
|
2018-07-24 00:21:21 +01:00
|
|
|
{
|
2018-08-14 08:40:55 +01:00
|
|
|
setStepSize(clockRate, kClockMultiplier);
|
2018-07-24 00:21:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void i2cDecoder::run()
|
|
|
|
{
|
2018-09-04 09:55:03 +01:00
|
|
|
qDebug() << "i2cDecoder::run()";
|
2018-08-02 09:27:09 +01:00
|
|
|
while (serialDistance(sda) > SERIAL_DELAY * sda->sampleRate_bit)
|
|
|
|
{
|
|
|
|
updateBitValues();
|
|
|
|
runStateMachine();
|
|
|
|
serialPtr_bit += stepSize;
|
2018-09-04 09:55:03 +01:00
|
|
|
qDebug() << serialPtr_bit;
|
|
|
|
currentStepIndex = (currentStepIndex + 1) % stepsPerBit;
|
2018-08-02 09:27:09 +01:00
|
|
|
}
|
2018-07-24 00:21:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int i2cDecoder::serialDistance(isoBuffer* buffer)
|
|
|
|
{
|
|
|
|
int back_bit = buffer->back * 8;
|
|
|
|
int bufferEnd_bit = buffer->bufferEnd * 8;
|
2018-08-02 09:27:09 +01:00
|
|
|
if (back_bit >= serialPtr_bit)
|
2018-07-24 00:21:21 +01:00
|
|
|
return back_bit - serialPtr_bit;
|
|
|
|
else
|
|
|
|
return bufferEnd_bit - serialPtr_bit + back_bit;
|
|
|
|
}
|
2018-07-31 00:05:58 +01:00
|
|
|
|
|
|
|
void i2cDecoder::updateBitValues(){
|
|
|
|
int coord_byte = serialPtr_bit/8;
|
|
|
|
int coord_bit = serialPtr_bit - (8*coord_byte);
|
|
|
|
unsigned char dataByteSda = sda->buffer[coord_byte];
|
|
|
|
unsigned char dataByteScl = scl->buffer[coord_byte];
|
|
|
|
unsigned char mask = (1 << coord_bit);
|
2018-11-03 23:07:15 +00:00
|
|
|
previousSdaValue = currentSdaValue;
|
|
|
|
previousSclValue = currentSclValue;
|
2018-07-31 00:05:58 +01:00
|
|
|
currentSdaValue = dataByteSda & mask;
|
|
|
|
currentSclValue = dataByteScl & mask;
|
|
|
|
}
|
2018-08-02 09:27:09 +01:00
|
|
|
|
2018-08-14 08:40:55 +01:00
|
|
|
// Step size should be a multiple of the clock rate; we need >1 clock cycle resolution.
|
|
|
|
void i2cDecoder::setStepSize(uint32_t clockRate, uint32_t multiplier)
|
2018-08-02 09:27:09 +01:00
|
|
|
{
|
2018-09-04 09:55:03 +01:00
|
|
|
stepSize = (double)((sda->sampleRate_bit)/clockRate)/(double)multiplier;
|
2018-08-14 08:40:55 +01:00
|
|
|
stepsPerBit = multiplier;
|
2018-08-02 09:27:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void i2cDecoder::runStateMachine()
|
|
|
|
{
|
2018-11-03 23:07:15 +00:00
|
|
|
edge sdaEdge = edgeDetection(currentSdaValue, previousSdaValue);
|
2018-08-08 00:31:05 +01:00
|
|
|
edge sclEdge = edgeDetection(currentSclValue, previousSclValue);
|
2018-09-04 09:55:03 +01:00
|
|
|
|
2018-11-03 23:07:15 +00:00
|
|
|
// if (sdaEdge == edge::rising || sdaEdge == edge::falling)
|
|
|
|
// qDebug() << "sdaEdge";
|
|
|
|
// if (sclEdge == edge::rising || sclEdge == edge::falling)
|
|
|
|
// qDebug() << "sclEdge";
|
|
|
|
|
|
|
|
qDebug() << "sdaEdge" << (uint8_t)sdaEdge << "sclEdge" << (uint8_t)sclEdge;
|
2018-08-08 09:58:41 +01:00
|
|
|
|
|
|
|
if ((sdaEdge == edge::rising) && (sclEdge == edge::falling)) // INVALID STATE TRANSITION
|
|
|
|
{
|
|
|
|
state = transmissionState::unknown;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-08 00:31:05 +01:00
|
|
|
if ((sdaEdge == edge::rising) && (sclEdge == edge::held_high)) // START
|
|
|
|
{
|
2018-08-08 09:58:41 +01:00
|
|
|
startCondition();
|
2018-08-08 00:31:05 +01:00
|
|
|
return;
|
|
|
|
}
|
2018-08-08 09:58:41 +01:00
|
|
|
|
2018-08-08 00:31:05 +01:00
|
|
|
if ((sdaEdge == edge::falling) && (sclEdge == edge::held_high)) // STOP
|
|
|
|
{
|
2018-08-08 09:58:41 +01:00
|
|
|
stopCondition();
|
2018-08-08 00:31:05 +01:00
|
|
|
return;
|
|
|
|
}
|
2018-08-08 09:35:26 +01:00
|
|
|
|
|
|
|
switch (state)
|
|
|
|
{
|
|
|
|
case transmissionState::idle:
|
|
|
|
return;
|
|
|
|
case transmissionState::address:
|
|
|
|
decodeAddress(sdaEdge, sclEdge);
|
|
|
|
break;
|
|
|
|
case transmissionState::data:
|
|
|
|
decodeData(sdaEdge, sclEdge);
|
|
|
|
break;
|
|
|
|
}
|
2018-08-02 09:27:09 +01:00
|
|
|
}
|
2018-08-08 00:19:30 +01:00
|
|
|
|
|
|
|
edge i2cDecoder::edgeDetection(uint8_t current, uint8_t prev)
|
|
|
|
{
|
|
|
|
if (current && prev)
|
|
|
|
return edge::held_high;
|
|
|
|
if (!current && !prev)
|
|
|
|
return edge::held_low;
|
|
|
|
if (current && !prev)
|
|
|
|
return edge::rising;
|
2018-09-04 09:55:03 +01:00
|
|
|
if (!current && prev)
|
2018-08-08 00:19:30 +01:00
|
|
|
return edge::falling;
|
2018-09-04 09:55:03 +01:00
|
|
|
|
|
|
|
throw std::runtime_error("i2c Edge Detection critical failure");
|
2018-08-08 00:19:30 +01:00
|
|
|
}
|
2018-08-08 09:35:26 +01:00
|
|
|
|
|
|
|
void i2cDecoder::decodeAddress(edge sdaEdge, edge sclEdge)
|
|
|
|
{
|
2018-08-14 08:40:55 +01:00
|
|
|
// Sample in the middle of the bits!
|
|
|
|
if (currentStepIndex != (stepsPerBit/2))
|
|
|
|
return;
|
|
|
|
|
2018-08-08 10:14:08 +01:00
|
|
|
// Read in the next bit.
|
2018-08-08 09:58:41 +01:00
|
|
|
if (sdaEdge == edge::rising && sclEdge == edge::held_high)
|
|
|
|
address |= 0x0001;
|
|
|
|
else if (sdaEdge == edge::rising && sclEdge == edge::held_low)
|
|
|
|
address &= 0xFFFE;
|
|
|
|
|
|
|
|
address = address << 1;
|
2018-08-08 09:35:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void i2cDecoder::decodeData(edge sdaEdge, edge sclEdge)
|
|
|
|
{
|
2018-08-14 08:40:55 +01:00
|
|
|
// Sample in the middle of the bits!
|
|
|
|
if (currentStepIndex != (stepsPerBit/2))
|
|
|
|
return;
|
|
|
|
|
2018-08-08 10:14:08 +01:00
|
|
|
// Read in the next bit.
|
|
|
|
if(currentBitIndex < 8)
|
|
|
|
{
|
|
|
|
if (sdaEdge == edge::rising && sclEdge == edge::held_high)
|
|
|
|
currentDataByte |= 0x01;
|
|
|
|
else if (sdaEdge == edge::rising && sclEdge == edge::held_low)
|
|
|
|
currentDataByte &= 0xFE;
|
|
|
|
|
|
|
|
currentDataByte = currentDataByte << 1;
|
|
|
|
currentBitIndex++;
|
|
|
|
}
|
|
|
|
else // Full byte received, check for ACK.
|
|
|
|
{
|
2018-08-08 10:20:32 +01:00
|
|
|
dataByteCompleted(currentDataByte, sclEdge == edge::held_low);
|
|
|
|
currentBitIndex = 0;
|
2018-08-08 10:14:08 +01:00
|
|
|
}
|
2018-08-08 09:35:26 +01:00
|
|
|
}
|
2018-08-08 09:58:41 +01:00
|
|
|
|
|
|
|
void i2cDecoder::startCondition()
|
|
|
|
{
|
2018-08-08 10:14:08 +01:00
|
|
|
currentBitIndex = 0;
|
2018-08-14 08:40:55 +01:00
|
|
|
currentStepIndex = 0;
|
2018-08-08 10:14:08 +01:00
|
|
|
address = 0x0000;
|
|
|
|
state = transmissionState::address;
|
2018-11-03 23:07:15 +00:00
|
|
|
qDebug() << "I2C START";
|
2018-08-08 09:58:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void i2cDecoder::stopCondition()
|
|
|
|
{
|
|
|
|
switch (state)
|
|
|
|
{
|
2018-08-08 10:14:08 +01:00
|
|
|
case transmissionState::address:
|
|
|
|
currentBitIndex = 0;
|
2018-08-14 08:40:55 +01:00
|
|
|
currentStepIndex = 0;
|
2018-08-08 10:14:08 +01:00
|
|
|
state = transmissionState::data;
|
|
|
|
currentDataByte = 0;
|
|
|
|
break;
|
|
|
|
case transmissionState::data:
|
|
|
|
state = transmissionState::idle;
|
|
|
|
break;
|
2018-08-08 09:58:41 +01:00
|
|
|
}
|
2018-11-03 23:07:15 +00:00
|
|
|
qDebug() << "I2C STOP";
|
2018-08-08 09:58:41 +01:00
|
|
|
}
|
2018-08-12 07:21:05 +01:00
|
|
|
|
|
|
|
void i2cDecoder::dataByteCompleted(uint8_t byte, bool ACKed)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|