Skip to content

Add writeWord writeBlock #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion src/sfeTk/sfeTkIBus.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,32 @@ class sfeTkIBus
{
public:
/**--------------------------------------------------------------------------
* @brief Write a single byte to the device*
* @brief Send a single byte to the device*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since all the methods use a "write*" naming pattern, shouldn't this be Write?

FWIW: Normally send/receive are used with network based operations - at least in my experience ....

Copy link
Contributor Author

@edspark edspark Jun 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're completely right. I was trying to get at the fact that it doesn't physically write bits/bytes to a register and so "send" seemed to fit. However, you're write (a joke there). I'll adjust to this: "Write a single byte, without indexing to a register". Something to that effect. I also have a few more things that I want to add to this pull request.

* @param data Data to write.
*
* @retval sfeTkError_t - kSTkErrOk on successful execution.
*
*/
virtual sfeTkError_t writeByte(uint8_t data) = 0;

/**--------------------------------------------------------------------------
* @brief Send a word to the device.
* @param data Data to write.
*
* @retval sfeTkError_t - kSTkErrOk on successful execution.
*
*/
virtual sfeTkError_t writeWord(uint16_t data) = 0;

/**--------------------------------------------------------------------------
* @brief Send an array of data to the device.
* @param data Data to write.
*
* @retval sfeTkError_t - kSTkErrOk on successful execution.
*
*/
virtual sfeTkError_t writeBlock(const uint8_t *data, size_t length) = 0;

/**--------------------------------------------------------------------------
* @brief Write a single byte to the given register
*
Expand All @@ -106,6 +124,45 @@ class sfeTkIBus
*/
virtual sfeTkError_t writeRegisterByte(uint8_t devReg, uint8_t data) = 0;

/**
@brief Reads a byte of data from the device.

@note sfeTkIBus interface method

@param dataToWrite The data to write to the device.
@param[out] data Data to read.

@retval kStkErrOk on success
*/
virtual sfeTkError_t readByte(uint8_t dataToWrite, uint8_t &data) = 0;

/**
@brief Reads a word of data from the device.

@note sfeTkIBus interface method

@param dataToWrite The data to write to the device.
@param[out] data Data to read.

@retval kSTkErrOk on success
*/
virtual sfeTkError_t readWord(uint8_t dataToWrite, uint16_t &data) = 0;

/**
@brief Reads a block of data from the device.

@note sfeTkIBus interface method

@param dataToWrite The data to write to the device.
@param[out] data Data buffer to read into
@param numBytes Number of bytes to read/length of data buffer
@param[out] readBytes - Number of bytes read


@retval kSTkErrOk on success
*/
virtual sfeTkError_t readBlock(uint8_t dataToWrite, uint8_t *data, size_t numBytes, size_t &readBytes) = 0;

/**--------------------------------------------------------------------------
* @brief Write a single word (16 bit) to the given register
*
Expand Down
153 changes: 152 additions & 1 deletion src/sfeTkArdI2C.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include "sfeTkArdI2C.h"
#include <cstddef>
#include <cstdint>

//---------------------------------------------------------------------------------
// init()
Expand Down Expand Up @@ -87,7 +89,7 @@ sfeTkError_t sfeTkArdI2C::ping()
//---------------------------------------------------------------------------------
// writeByte()
//
// Writes a single byte to the device.
// Writes a single byte to the device, without indexing to a register.
//
// Returns true on success, false on failure
//
Expand All @@ -102,6 +104,40 @@ sfeTkError_t sfeTkArdI2C::writeByte(uint8_t dataToWrite)
return _i2cPort->endTransmission() == 0 ? kSTkErrOk : kSTkErrFail;
}

//---------------------------------------------------------------------------------
// writeWord()
//
// Writes a word to the device, without indexing to a register.
//
// Returns true on success, false on failure
//
sfeTkError_t sfeTkArdI2C::writeWord(uint16_t dataToWrite)
{
if (!_i2cPort)
return kSTkErrBusNotInit;

return writeBlock((uint8_t *)&dataToWrite, sizeof(uint16_t));
}

//---------------------------------------------------------------------------------
// writeBlock()
//
// Writes a word to the device, without indexing to a register.
//
// Returns true on success, false on failure
//
sfeTkError_t sfeTkArdI2C::writeBlock(const uint8_t *data, size_t length)
{
if (!_i2cPort)
return kSTkErrBusNotInit;

// do the Arduino I2C work
_i2cPort->beginTransmission(address());
_i2cPort->write(data, (int)length);

return _i2cPort->endTransmission() == 0 ? kSTkErrOk : kSTkErrFail;
}

//---------------------------------------------------------------------------------
// writeRegisterByte()
//
Expand Down Expand Up @@ -183,6 +219,121 @@ sfeTkError_t sfeTkArdI2C::writeRegister16Region(uint16_t devReg, const uint8_t *
return writeRegisterRegionAddress((uint8_t *)&devReg, 2, data, length);
}

//---------------------------------------------------------------------------------
// readByte()
//
// Reads a byte from the device, without indexing to a register.
//
// Returns true on success, false on failure
//
sfeTkError_t sfeTkArdI2C::readByte(uint8_t dataToWrite, uint8_t &dataToRead)
{
if (!_i2cPort)
return kSTkErrBusNotInit;

// Return value
uint8_t result = 0;

int nData = 0;

_i2cPort->beginTransmission(address());
_i2cPort->write(dataToWrite);
_i2cPort->endTransmission(stop());
_i2cPort->requestFrom(address(), (uint8_t)1);

while (_i2cPort->available()) // slave may send less than requested
{
result = _i2cPort->read(); // receive a byte as a proper uint8_t
nData++;
}

if (nData == sizeof(uint8_t)) // Only update outputPointer if a single byte was returned
dataToRead = result;

return (nData == sizeof(uint8_t) ? kSTkErrOk : kSTkErrFail);
}


//---------------------------------------------------------------------------------
// readWord()
//
// Reads a word from the device, without indexing to a register.
//
// Returns true on success, false on failure
//
sfeTkError_t sfeTkArdI2C::readWord(uint8_t dataToWrite, uint16_t &dataToRead)
{
if (!_i2cPort)
return kSTkErrBusNotInit;

size_t nRead;
sfeTkError_t retval = readBlock(dataToWrite, (uint8_t *)&dataToRead, sizeof(uint16_t), nRead);

return (retval == kSTkErrOk && nRead == sizeof(uint16_t) ? kSTkErrOk : retval);
}

//---------------------------------------------------------------------------------
// readBlock()
//
// Reads a block of data from the device, without indexing to a register.
//
// Returns the number of bytes written, < 0 is an error
//
sfeTkError_t sfeTkArdI2C::readBlock(uint8_t dataToWrite, uint8_t *data, size_t numBytes, size_t &readBytes)
{

// got port
if (!_i2cPort)
return kSTkErrBusNotInit;

// Buffer valid?
if (!data)
return kSTkErrBusNullBuffer;

readBytes = 0;

uint16_t nOrig = numBytes; // original number of bytes.
uint8_t nChunk;
uint16_t nReturned;
uint16_t i; // counter in loop
bool bFirstInter = true; // Flag for first iteration - used to send devRegister

while (numBytes > 0)
{
if (bFirstInter)
{
_i2cPort->beginTransmission(address());
_i2cPort->write(dataToWrite);
if (_i2cPort->endTransmission(stop()) != 0)
return kSTkErrFail; // error with the end transmission

bFirstInter = false;
}

// We're chunking in data - keeping the max chunk to kMaxI2CBufferLength
nChunk = numBytes > _bufferChunkSize ? _bufferChunkSize : numBytes;

// Request the bytes. If this is the last chunk, always send a stop
nReturned = _i2cPort->requestFrom((int)address(), (int)nChunk, (int)(nChunk == numBytes ? true : stop()));

// No data returned, no dice
if (nReturned == 0)
return kSTkErrBusUnderRead; // error

// Copy the retrieved data chunk to the current index in the data segment
for (i = 0; i < nReturned; i++)
*data++ = _i2cPort->read();

// Decrement the amount of data received from the overall data request amount
numBytes = numBytes - nReturned;

} // end while

readBytes = nOrig - numBytes; // Bytes read.

return (readBytes == nOrig) ? kSTkErrOk : kSTkErrBusUnderRead; // Success
}

//---------------------------------------------------------------------------------

/**
Expand Down
61 changes: 60 additions & 1 deletion src/sfeTkArdI2C.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class sfeTkArdI2C : public sfeTkII2C
sfeTkError_t ping();

/**
@brief Write a single byte to the device
@brief Sends a single byte to the device
@note sfeTkIBus interface method

@param data Data to write.
Expand All @@ -118,6 +118,26 @@ class sfeTkArdI2C : public sfeTkII2C
*/
sfeTkError_t writeByte(uint8_t data);

/**
@brief Sends a word to the device.
@note sfeTkIBus interface method

@param data Data to write.

@retval returns kStkErrOk on success
*/
sfeTkError_t writeWord(uint16_t data);

/**
@brief Sends a block of data to the device.
@note sfeTkIBus interface method

@param data Data to write.

@retval returns kStkErrOk on success
*/
sfeTkError_t writeBlock(const uint8_t *data, size_t length);

/**
@brief Write a single byte to the given register
@note sfeTkIBus interface method
Expand Down Expand Up @@ -166,6 +186,45 @@ class sfeTkArdI2C : public sfeTkII2C
*/
sfeTkError_t writeRegister16Region(uint16_t devReg, const uint8_t *data, size_t length);

/**
@brief Reads a byte of data from the device.

@note sfeTkIBus interface method

@param dataToWrite The data to write to the device.
@param[out] data Data to read.

@retval kStkErrOk on success
*/
sfeTkError_t readByte(uint8_t dataToWrite, uint8_t &data);

/**
@brief Reads a word of data from the device.

@note sfeTkIBus interface method

@param dataToWrite The data to write to the device.
@param[out] data Data to read.

@retval kSTkErrOk on success
*/
sfeTkError_t readWord(uint8_t dataToWrite, uint16_t &data);

/**
@brief Reads a block of data from the device.

@note sfeTkIBus interface method

@param dataToWrite The data to write to the device.
@param[out] data Data buffer to read into
@param numBytes Number of bytes to read/length of data buffer
@param[out] readBytes - Number of bytes read


@retval kSTkErrOk on success
*/
sfeTkError_t readBlock(uint8_t dataToWrite, uint8_t *data, size_t numBytes, size_t &readBytes);

/**
@brief Reads a byte of data from the given register.

Expand Down