Labrador/Desktop_Interface/i2cdecoder.cpp

148 lines
3.3 KiB
C++
Raw Normal View History

2018-07-24 00:21:21 +01:00
#include "i2cdecoder.h"
2018-08-08 00:19:30 +01:00
using namespace i2c;
2018-08-02 09:27:09 +01:00
i2cDecoder::i2cDecoder(isoBuffer* sda_in, isoBuffer* scl_in, uint32_t clockRate) : QObject(nullptr)
2018-07-24 00:21:21 +01:00
{
sda = sda_in;
scl = scl_in;
2018-08-02 09:27:09 +01:00
setStepSize(clockRate);
2018-07-24 00:21:21 +01:00
}
void i2cDecoder::run()
{
2018-08-02 09:27:09 +01:00
while (serialDistance(sda) > SERIAL_DELAY * sda->sampleRate_bit)
{
updateBitValues();
runStateMachine();
serialPtr_bit += stepSize;
}
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);
currentSdaValue = dataByteSda & mask;
currentSclValue = dataByteScl & mask;
}
2018-08-02 09:27:09 +01:00
void i2cDecoder::setStepSize(uint32_t clockRate)
{
stepSize = (double)((sda->sampleRate_bit)/clockRate)/2.0;
if (stepSize > (SERIAL_DELAY * sda->sampleRate_bit)/2)
stepSize = SERIAL_DELAY * sda->sampleRate_bit / 2;
}
void i2cDecoder::runStateMachine()
{
edge sdaEdge = edgeDetection(currentSdaValue, previousSdaValue);
edge sclEdge = edgeDetection(currentSclValue, previousSclValue);
2018-08-08 09:58:41 +01:00
if ((sdaEdge == edge::rising) && (sclEdge == edge::falling)) // INVALID STATE TRANSITION
{
state = transmissionState::unknown;
return;
}
if ((sdaEdge == edge::rising) && (sclEdge == edge::held_high)) // START
{
2018-08-08 09:58:41 +01:00
startCondition();
return;
}
2018-08-08 09:58:41 +01:00
if ((sdaEdge == edge::falling) && (sclEdge == edge::held_high)) // STOP
{
2018-08-08 09:58:41 +01:00
stopCondition();
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;
if (!current &&!prev)
return edge::falling;
}
2018-08-08 09:35:26 +01:00
void i2cDecoder::decodeAddress(edge sdaEdge, edge sclEdge)
{
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-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 09:35:26 +01:00
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;
address = 0x0000;
state = transmissionState::address;
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;
state = transmissionState::data;
currentDataByte = 0;
break;
case transmissionState::data:
state = transmissionState::idle;
break;
2018-08-08 09:58:41 +01:00
}
}