//============================================================================
/*! \file I2cDevice.cxx
* \author W.F.J.Mueller/GSI, based on earlier work of Norbert Abel/KIP
*/
//============================================================================
#include "roc/I2cDevice.h"
#include "roc/defines_roc.h"
#include "roc/defines_i2c.h"
using roc::Board;
/*!
* \class roc::I2cDevice
* \brief Base class to represent a ROC I2C Bus Device.
*
* A ROC can have several I2C bus ports. They are served by a common control
* logic, a switch determines which port is active at a given time. Each bus
* can have several devices attached, identified by a slave address.
*
* The class holds the addressing information needed to reach the \c I2cDevice:
* \li the ROC board pointer (in the base class)
* \li the I2C bus port number
* \li the I2C device slave address
*/
//----------------------------------------------------------------------------
//! Default constructor to make old ROOT hapy
roc::I2cDevice::I2cDevice() :
roc::Peripheral(), fPort(0), fSlaveAddr(0)
{
}
//----------------------------------------------------------------------------
//! Constructor with full addressing path information.
/*!
* Sets up \c I2cDevice object with full addressing information
* \param board ROC board pointer
* \param port the I2C bus port number
* \param addr the I2C device slave address
*/
roc::I2cDevice::I2cDevice(roc::Board* board, int port, uint8_t addr) :
roc::Peripheral(board), fPort(port), fSlaveAddr(addr)
{
}
//----------------------------------------------------------------------------
roc::I2cDevice::~I2cDevice()
{
}
//----------------------------------------------------------------------------
//! Write to device register with optional readback verification.
/*!
* Writes the 8bit value \a val to device register \a reg. If \a veri
* is \c true, the register contents is read back and verified.
* The I2C status is checked for error flags after the write and
* optional read cycle.
*
* \param reg device register number
* \param val value
* \param veri if \c true readback verification done (default is \c false)
* \returns see \ref roc_board_opererr
*
* \sa getRegister(), setRegisterVerify()
*/
int roc::I2cDevice::setRegister(uint8_t reg, uint8_t val, bool veri)
{
bool isput[7];
uint32_t addr[7];
uint32_t data[7];
int rc;
isput[0] = true; addr[0] = ROC_NX_I2C_SWITCH; data[0] = fPort;
isput[1] = true; addr[1] = ROC_NX_I2C_SLAVEADDR; data[1] = fSlaveAddr;
isput[2] = true; addr[2] = ROC_NX_I2C_REGISTER; data[2] = reg;
isput[3] = true; addr[3] = ROC_NX_I2C_DATA; data[3] = val;
isput[4] = false; addr[4] = ROC_NX_I2C_ERROR;
isput[5] = false; addr[5] = ROC_NX_I2C_DATA;
isput[6] = false; addr[6] = ROC_NX_I2C_ERROR;
int nop = veri ? 7 : 5;
rc = board().operGen(isput, addr, data, nop);
if (rc == 0 && data[4] != 0) { // check I2C bus error on put
rc = Board::operErrBuild(Board::kOperBusErr, 0);
}
if (veri) {
if (rc == 0 && data[6] != 0) { // check I2C bus error on readback
rc = Board::operErrBuild(Board::kOperBusErr, 1);
}
if (rc == 0 && val != (data[5]&0xff)) { // check readback value
rc = Board::kOperVerifyErr;
}
}
return rc;
}
//----------------------------------------------------------------------------
//! Read 8 bit from device register.
/*!
* Reads an 8bit value from device register \a reg and checks
* I2C status for error flags.
*
* \param reg device register number
* \param val value
* \returns see \ref roc_board_opererr
*
* \sa setRegister()
*/
int roc::I2cDevice::getRegister(uint8_t reg, uint8_t& val)
{
bool isput[5];
uint32_t addr[5];
uint32_t data[5];
int rc;
isput[0] = true; addr[0] = ROC_NX_I2C_SWITCH; data[0] = fPort;
isput[1] = true; addr[1] = ROC_NX_I2C_SLAVEADDR; data[1] = fSlaveAddr;
isput[2] = true; addr[2] = ROC_NX_I2C_REGISTER; data[2] = reg;
isput[3] = false; addr[3] = ROC_NX_I2C_DATA;
isput[4] = false; addr[4] = ROC_NX_I2C_ERROR;
rc = board().operGen(isput, addr, data, 5);
val = uint8_t(data[3]);
if (rc == 0 && data[4] != 0) { // check I2C bus error on get
rc = Board::kOperBusErr;
}
return rc;
}
//----------------------------------------------------------------------------
//! Read 16 bit from device register.
/*!
* Reads an 16bit value from device register \a reg and checks
* I2C status for error flags.
*
* \param reg device register number
* \param val value
* \returns see \ref roc_board_opererr
*
*/
int roc::I2cDevice::getRegister16(uint8_t reg, uint16_t& val)
{
bool isput[7];
uint32_t addr[7];
uint32_t data[7];
int rc;
isput[0] = true; addr[0] = ROC_NX_I2C_SWITCH; data[0] = fPort;
isput[1] = true; addr[1] = ROC_NX_I2C_SLAVEADDR; data[1] = fSlaveAddr;
isput[2] = true; addr[2] = ROC_NX_I2C_REGISTER; data[2] = reg;
isput[3] = true; addr[3] = ROC_NX_I2C_READ16; data[3] = 1;
isput[4] = false; addr[4] = ROC_NX_I2C_DATA;
isput[5] = false; addr[5] = ROC_NX_I2C_ERROR;
isput[6] = true; addr[6] = ROC_NX_I2C_READ16; data[6] = 0;
rc = board().operGen(isput, addr, data, 7);
val = uint16_t(data[4]);
if (rc == 0 && data[5] != 0) { // check I2C bus error on get
rc = Board::kOperBusErr;
}
return rc;
}
//----------------------------------------------------------------------------
//! Write to device register and return the readback value.
/*!
* Writes the 8bit value \a valset to device register \a reg, reads
* it back and returns the readback value in \a valget.
* The I2C status is checked for error flags after the write and read cycle.
*
* \param reg device register number
* \param valset value to be written
* \param valget value returned from readback
* \returns see \ref roc_board_opererr
*
* \note The method just returns the readback value and does not test whether
* \a valget equals \a valset, thus never returns a Board::kOperVerifyErr
* return code.
*
* \sa setRegister(), getRegister()
*/
int roc::I2cDevice::setRegisterVerify(uint8_t reg, uint8_t valset,
uint8_t& valget)
{
bool isput[7];
uint32_t addr[7];
uint32_t data[7];
int rc;
isput[0] = true; addr[0] = ROC_NX_I2C_SWITCH; data[0] = fPort;
isput[1] = true; addr[1] = ROC_NX_I2C_SLAVEADDR; data[1] = fSlaveAddr;
isput[2] = true; addr[2] = ROC_NX_I2C_REGISTER; data[2] = reg;
isput[3] = true; addr[3] = ROC_NX_I2C_DATA; data[3] = valset;
isput[4] = false; addr[4] = ROC_NX_I2C_ERROR;
isput[5] = false; addr[5] = ROC_NX_I2C_DATA;
isput[6] = false; addr[6] = ROC_NX_I2C_ERROR;
rc = board().operGen(isput, addr, data, 7);
valget = uint8_t(data[5]);
if (rc == 0 && data[4] != 0) { // check I2C bus error on put
rc = Board::operErrBuild(Board::kOperBusErr, 0);
}
if (rc == 0 && data[6] != 0) { // check I2C bus error on readback
rc = Board::operErrBuild(Board::kOperBusErr, 1);
}
return rc;
}
//----------------------------------------------------------------------------
//! Write to device register array with optional readback verification.
/*!
* Writes the \a nreg 8bit values from array \a val to an array of device
* registers starting at register number \a reg. When \a veri is \c true,
* each value is readback and verified.
* The I2C error flags are checked for each transfer, writing is stopped
* when the first error is detected.
*
* \param reg first device register number
* \param val value array
* \param nreg number of registers to write
* \param veri if \c true readback verification done (default is \c false)
* \returns see \ref roc_board_opererr
*
* \sa getRegisterArray()
*/
int roc::I2cDevice::setRegisterArray(uint8_t reg, const uint8_t *val, int nreg,
bool veri)
{
for (int i=0; iaddRocAddrMapping("ROC_NX_I2C_DATA", ROC_NX_I2C_DATA);
board->addRocAddrMapping("ROC_NX_I2C_SLAVEADDR", ROC_NX_I2C_SLAVEADDR);
board->addRocAddrMapping("ROC_NX_I2C_REGISTER", ROC_NX_I2C_REGISTER);
board->addRocAddrMapping("ROC_NX_I2C_ERROR", ROC_NX_I2C_ERROR);
board->addRocAddrMapping("ROC_NX_I2C_SWITCH", ROC_NX_I2C_SWITCH);
board->addRocAddrMapping("ROC_NX_I2C_READ16", ROC_NX_I2C_READ16);
}
//----------------------------------------------------------------------------