* Add WriteBulk and ReadOnly to C++ I2C

Change-Id: If6082f6b92b4be5e328278ba536d5a7681082c9f (+4 squashed commit)

Squashed commit:

[86b4ae7] * Port I2C to roboRIO in JNI and Java. Left read method as a transaction and added readOnly. Left write as a single byte and added writeBulk. Need to go back to C++ and update to match.

Change-Id: I290d84211a4b7bb942d785730c0e6929449cf69f

[7d37419] * Remove HiTechnic sensors from Java. May be added back later as examples

Change-Id: Ie93e23a70fd953c99c03d50d9529220f86d32e03

[e62bfbf] * I2C ported to roboRIO i2clib in HAL and C++

Change-Id: Idb0e8cee5a1e8c1a0b0733ca94b528f659352915

[1059a48] * Remove HiTechnic sensors (Lego connector) may be added back as examples later

Change-Id: I84b8e1e022db2c69d487ed9ad5b3ec0e7ea57282 (+2 squashed commit)

Squashed commit:

[e62bfbf] * I2C ported to roboRIO i2clib in HAL and C++

Change-Id: Idb0e8cee5a1e8c1a0b0733ca94b528f659352915

[1059a48] * Remove HiTechnic sensors (Lego connector) may be added back as examples later

Change-Id: I84b8e1e022db2c69d487ed9ad5b3ec0e7ea57282
This commit is contained in:
Kevin O'Connor
2014-06-18 15:38:02 -04:00
parent 0f8c83f693
commit 605148456e
21 changed files with 430 additions and 1392 deletions

View File

@@ -9,6 +9,7 @@
#include "NetworkCommunication/LoadOut.h"
#include <stdio.h>
#include <math.h>
#include "i2clib/i2c-lib.h"
static const uint32_t kExpectedLoopTiming = 40;
static const uint32_t kDigitalPins = 20;
@@ -52,7 +53,9 @@ struct DigitalPort {
MUTEX_ID digitalDIOSemaphore = NULL;
MUTEX_ID digitalRelaySemaphore = NULL;
MUTEX_ID digitalPwmSemaphore = NULL;
MUTEX_ID digitalI2CSemaphore = NULL;
MUTEX_ID digitalI2COnBoardSemaphore = NULL;
MUTEX_ID digitalI2CMXPSemaphore = NULL;
tDIO* digitalSystem = NULL;
tRelay* relaySystem = NULL;
tPWM* pwmSystem = NULL;
@@ -61,6 +64,11 @@ Resource *DO_PWMGenerators = NULL;
bool digitalSystemsInitialized = false;
uint8_t i2COnboardObjCount = 0;
uint8_t i2CMXPObjCount = 0;
uint8_t i2COnBoardHandle = 0;
uint8_t i2CMXPHandle = 0;
/**
* Initialize the digital modules.
*/
@@ -76,7 +84,8 @@ void initializeDigital(int32_t *status) {
// Create a semaphore to protect changes to the DO PWM config
digitalPwmSemaphore = initializeMutexRecursive();
digitalI2CSemaphore = initializeMutexRecursive();
digitalI2COnBoardSemaphore = initializeMutexRecursive();
digitalI2CMXPSemaphore = initializeMutexRecursive();
Resource::CreateResourceObject(&DIOChannels, tDIO::kNumSystems * kDigitalPins);
Resource::CreateResourceObject(&DO_PWMGenerators, tDIO::kNumPWMDutyCycleAElements + tDIO::kNumPWMDutyCycleBElements);
@@ -1539,86 +1548,153 @@ uint32_t readSPI(void* spi_pointer, bool initiate, int32_t *status) {return 0;}
void resetSPI(void* spi_pointer, int32_t *status) {}
void clearSPIReceivedData(void* spi_pointer, int32_t *status) {}
/**
* Generic transaction.
*
* This is a lower-level interface to the I2C hardware giving you more control over each transaction.
*
* @param dataToSend Buffer of data to send as part of the transaction.
* @param sendSize Number of bytes to send as part of the transaction. [0..6]
* @param dataReceived Buffer to read data into.
* @param receiveSize Number of byted to read from the device. [0..7]
* @return Transfer Aborted... false for success, true for aborted.
/*
* Initialize the I2C port. Opens the port if necessary and saves the handle.
* If opening the MXP port, also sets up the pin functions appropriately
* @param port The port to open, 0 for the on-board, 1 for the MXP.
*/
bool doI2CTransaction(uint8_t address, bool compatibilityMode, uint8_t *dataToSend,
uint8_t sendSize, uint8_t *dataReceived, uint8_t receiveSize,
int32_t *status) {
return doI2CTransactionWithModule(1, address, compatibilityMode, dataToSend, sendSize,
dataReceived, receiveSize, status);
void i2CInitialize(uint8_t port, int32_t *status) {
if(port > 1)
{
//Set port out of range error here
return;
}
MUTEX_ID lock = port == 0 ? digitalI2COnBoardSemaphore:digitalI2CMXPSemaphore;
{
Synchronized sync(lock);
if(port == 0) {
i2COnboardObjCount++;
if (i2COnBoardHandle > 0) return;
i2COnBoardHandle = i2clib_open("/dev/i2c-2");
} else if(port == 1) {
i2CMXPObjCount++;
if (i2CMXPHandle > 0) return;
initializeDigital(status);
digitalSystem->writeEnableMXPSpecialFunction(digitalSystem->readEnableMXPSpecialFunction(status)|0xC000, status);
i2CMXPHandle = i2clib_open("/dev/i2c-1");
}
return;
}
}
/**
* Generic transaction.
*
*
* This is a lower-level interface to the I2C hardware giving you more control over each transaction.
*
*
* @param dataToSend Buffer of data to send as part of the transaction.
* @param sendSize Number of bytes to send as part of the transaction. [0..6]
* @param dataReceived Buffer to read data into.
* @param receiveSize Number of byted to read from the device. [0..7]
* @param receiveSize Number of bytes to read from the device. [0..7]
* @return Transfer Aborted... false for success, true for aborted.
*/
bool doI2CTransactionWithModule(uint8_t module, uint8_t address, bool compatibilityMode,
uint8_t *dataToSend, uint8_t sendSize, uint8_t *dataReceived,
uint8_t receiveSize, int32_t *status) {
// initializeDigital(status);
// if (sendSize > 6) {
// *status = PARAMETER_OUT_OF_RANGE;
// // TODO: wpi_setWPIErrorWithContext(ParameterOutOfRange, "sendSize");
// return true;
// }
// if (receiveSize > 7) {
// *status = PARAMETER_OUT_OF_RANGE;
// // TODO: wpi_setWPIErrorWithContext(ParameterOutOfRange, "receiveSize");
// return true;
// }
int i2CTransaction(uint8_t port, uint8_t deviceAddress, uint8_t *dataToSend, uint8_t sendSize, uint8_t *dataReceived, uint8_t receiveSize)
{
if(port > 1) {
//Set port out of range error here
return -1;
}
/*if (sendSize > 6) // Optional, provides better error message. TODO: Are these limits still right? Implement error. Check for null buffer
{
wpi_setWPIErrorWithContext(ParameterOutOfRange, "sendSize");
return true;
}
if (receiveSize > 7) // Optional, provides better error message.
{
wpi_setWPIErrorWithContext(ParameterOutOfRange, "receiveSize");
return true;
}*/
int32_t handle = port == 0 ? i2COnBoardHandle:i2CMXPHandle;
MUTEX_ID lock = port == 0 ? digitalI2COnBoardSemaphore:digitalI2CMXPSemaphore;
// uint32_t data=0;
// uint32_t dataHigh=0;
// uint32_t i;
// for(i=0; i<sendSize && i<sizeof(data); i++) {
// data |= (uint32_t)dataToSend[i] << (8*i);
// }
// for(; i<sendSize; i++) {
// dataHigh |= (uint32_t)dataToSend[i] << (8*(i-sizeof(data)));
// }
{
Synchronized sync(lock);
return i2clib_writeread(handle, deviceAddress, (const char*) dataToSend, (int32_t) sendSize, (char*) dataReceived, (int32_t) receiveSize);
}
}
// bool aborted = true;
// {
// Synchronized sync(digitalI2CSemaphore);
// digitalModules[module]->writeI2CConfig_Address(address, status);
// digitalModules[module]->writeI2CConfig_BytesToWrite(sendSize, status);
// digitalModules[module]->writeI2CConfig_BytesToRead(receiveSize, status);
// if (sendSize > 0) digitalModules[module]->writeI2CDataToSend(data, status);
// if (sendSize > sizeof(data)) digitalModules[module]->writeI2CConfig_DataToSendHigh(dataHigh, status);
// digitalModules[module]->writeI2CConfig_BitwiseHandshake(compatibilityMode, status);
// uint8_t transaction = digitalModules[module]->readI2CStatus_Transaction(status);
// digitalModules[module]->strobeI2CStart(status);
// while(transaction == digitalModules[module]->readI2CStatus_Transaction(status)) delayTicks(1);
// while(!digitalModules[module]->readI2CStatus_Done(status)) delayTicks(1);
// aborted = digitalModules[module]->readI2CStatus_Aborted(status);
// if (receiveSize > 0) data = digitalModules[module]->readI2CDataReceived(status);
// if (receiveSize > sizeof(data)) dataHigh = digitalModules[module]->readI2CStatus_DataReceivedHigh(status);
// }
/**
* Execute a write transaction with the device.
*
* Write a single byte to a register on a device and wait until the
* transaction is complete.
*
* @param registerAddress The address of the register on the device to be written.
* @param data The byte to write to the register on the device.
* @return Transfer Aborted... false for success, true for aborted.
*/
int i2CWrite(uint8_t port, uint8_t deviceAddress, uint8_t* dataToSend, uint8_t sendSize)
{
if(port > 1) {
//Set port out of range error here
return -1;
}
/*if (sendSize > 6) // Optional, provides better error message. TODO: Are these limits still right? Implement error. Check for null buffer
{
wpi_setWPIErrorWithContext(ParameterOutOfRange, "sendSize");
return true;
}*/
int32_t handle = port == 0 ? i2COnBoardHandle:i2CMXPHandle;
MUTEX_ID lock = port == 0 ? digitalI2COnBoardSemaphore:digitalI2CMXPSemaphore;
{
Synchronized sync(lock);
return i2clib_write(handle, deviceAddress, (const char*) dataToSend, (int32_t) sendSize);
}
}
// for(i=0; i<receiveSize && i<sizeof(data); i++) {
// dataReceived[i] = (data >> (8*i)) & 0xFF;
// }
// for(; i<receiveSize; i++) {
// dataReceived[i] = (dataHigh >> (8*(i-sizeof(data)))) & 0xFF;
// }
// return aborted;
return false; // XXX: What happened to I2C?
/**
* Execute a read transaction with the device.
*
* Read 1 to 7 bytes from a device.
* Most I2C devices will auto-increment the register pointer internally
* allowing you to read up to 7 consecutive registers on a device in a
* single transaction.
*
* @param registerAddress The register to read first in the transaction.
* @param count The number of bytes to read in the transaction. [1..7]
* @param buffer A pointer to the array of bytes to store the data read from the device.
* @return Transfer Aborted... false for success, true for aborted.
*/
int i2CRead(uint8_t port, uint8_t deviceAddress, uint8_t *buffer, uint8_t count)
{
if(port > 1) {
//Set port out of range error here
return -1;
}
/* if (count < 1 || count > 7) Todo: Are these limits still right? Implement error
{
wpi_setWPIErrorWithContext(ParameterOutOfRange, "count");
return true;
}
if (buffer == NULL)
{
wpi_setWPIErrorWithContext(NullParameter, "buffer");
return true;
}*/
int32_t handle = port == 0 ? i2COnBoardHandle:i2CMXPHandle;
MUTEX_ID lock = port == 0 ? digitalI2COnBoardSemaphore:digitalI2CMXPSemaphore;
{
Synchronized sync(lock);
return i2clib_read(handle, deviceAddress, (char*) buffer, (int32_t) count);
}
}
void i2CClose(uint8_t port) {
if(port > 1) {
//Set port out of range error here
return;
}
MUTEX_ID lock = port == 0 ? digitalI2COnBoardSemaphore:digitalI2CMXPSemaphore;
{
Synchronized sync(lock);
if((port == 0 ? i2COnboardObjCount--:i2CMXPObjCount--) == 0) {
int32_t handle = port == 0 ? i2COnBoardHandle:i2CMXPHandle;
i2clib_close(handle);
}
}
return;
}