Skip to content

Commit

Permalink
Merge pull request #9 from zhengmaxwell/payload
Browse files Browse the repository at this point in the history
added read and write payload functions
  • Loading branch information
hmaarrfk authored Jun 3, 2021
2 parents 02e303e + a11f735 commit e0cc1a8
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 3 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
### 0.0.14

* Enable reading and writing a contiguous payload of bytes

### 0.0.13

* Ensure that the system is compiled with I2C support for Teensy 3.2

### 0.0.12

* Preliminary Teensy 4.0 Support

### 0.0.11

* Added the ability to talk to 1 byte register address I2C devices.
### 0.0.10

* Fix spi_transfer_bulk
Expand Down
12 changes: 12 additions & 0 deletions src/commandconstants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ int i2c_read_uint8(CommandRouter *cmd, int argc, const char **argv);
int i2c_read_no_register_uint8(CommandRouter *cmd, int argc, const char **argv);
int i2c_write_no_register_uint8(CommandRouter *cmd, int argc,
const char **argv);
int i2c_write_payload(CommandRouter *cmd, int argc, const char **argv);
int i2c_read_payload(CommandRouter *cmd, int argc, const char **argv);

// PWM Support
int analog_write(CommandRouter *cmd, int argc, const char **argv);
Expand Down Expand Up @@ -80,6 +82,16 @@ command_item_t command_list[] = {
"Write a uint8_t to the I2C bus without specifying a register address.",
"i2c_write_no_register_uint8 slave_address data",
i2c_write_no_register_uint8},
{"i2c_write_payload",
"Write up to 8 bytes to the I2C bus starting at a specified register "
"address.",
"i2c_write_payload slave_address register_address data num_bytes",
i2c_write_payload},
{"i2c_read_payload",
"Read up to 8 bytes from the I2C bus starting at a specified register "
"address.",
"i2c_read_payload slave_address register_address data num_bytes",
i2c_read_payload},
{"analog_write", "Write the duty cycle of the PWM",
"analog_write pin dutycycle", analog_write},
{"analog_write_frequency", "Write the frequency of the PWM",
Expand Down
63 changes: 63 additions & 0 deletions src/i2c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,69 @@ int I2CMaster::write_no_register_uint8(int slave_address, uint8_t data) {
return Wire.getError();
}

int I2CMaster::write_payload(int slave_address, int register_address,
uint8_t *data, int num_bytes) {
if (!this->is_initialized)
return ENODEV;

// Wire library uses 7 bit addresses
if (slave_8bit_address)
slave_address = slave_address >> 1;

Wire.beginTransmission(slave_address); // slave addr
this->_write_register_address(register_address);
Wire.write(data, num_bytes);
// blocking write (when not specified I2C_STOP is implicit)
Wire.endTransmission(I2C_STOP);

return Wire.getError();
}

int I2CMaster::read_payload(int slave_address, int register_address,
uint8_t *data, int num_bytes) {
if (!this->is_initialized)
return ENODEV;
// Wire library uses 7 bit addresses
if (slave_8bit_address)
slave_address = slave_address >> 1;
// Ensure the address is in write mode
uint8_t err;

Wire.beginTransmission(slave_address); // slave addr
// Write the MSB of the address first
this->_write_register_address(register_address);
Wire.endTransmission(
I2C_NOSTOP); // blocking write (when not specified I2C_STOP is implicit)
err = Wire.getError();
if (err) {
goto handle_error;
}

Wire.requestFrom(slave_address, num_bytes);
Wire.finish();
err = Wire.getError();
if (err) {
goto handle_error;
}

if (Wire.available() != num_bytes) {
err = 3;
goto handle_error;
}

for (int i = 0; i < num_bytes; i++) {
data[i] = Wire.readByte();
}

return 0;

handle_error:
while (Wire.available() != 0) {
Wire.readByte();
}
return err;
}

int I2CMaster::read_uint16(int slave_address, int register_address,
uint16_t &data) {
if (!this->is_initialized)
Expand Down
9 changes: 6 additions & 3 deletions src/i2c.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
// only support teensies 3.1, 3.2, 3.5, and 3.6
// See list of microcontroller units
// https://docs.platformio.org/en/latest/platforms/teensy.html
#if defined(TEENSYDUINO) && \
(defined(__MK20DX256__) || defined(__MK64FX512__) || \
defined(__MK66FX1M0__))
#if defined(TEENSYDUINO) && (defined(__MK20DX256__) || \
defined(__MK64FX512__) || defined(__MK66FX1M0__))
#define TEENSY_TO_ANY_HAS_I2C 1
#else
#define TEENSY_TO_ANY_HAS_I2C 0
Expand All @@ -25,6 +24,10 @@ class I2CMaster {
int read_uint8(int slave_address, int register_address, uint8_t &data);
int read_no_register_uint8(int slave_address, uint8_t &data);
int write_no_register_uint8(int slave_address, uint8_t data);
int write_payload(int slave_address, int register_address, uint8_t *data,
int num_bytes);
int read_payload(int slave_address, int register_address, uint8_t *data,
int num_bytes);

private:
void _write_register_address(int register_address);
Expand Down
61 changes: 61 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,67 @@ int i2c_write_uint8(CommandRouter *cmd, int argc, const char **argv) {
#endif
}

int i2c_write_payload(CommandRouter *cmd, int argc, const char **argv) {
#if TEENSY_TO_ANY_HAS_I2C
const int num_bytes_max = 8;
uint8_t data[num_bytes_max];
if (argc < 4)
return EINVAL;

int num_bytes = argc - 3;
if (num_bytes > num_bytes_max)
return EINVAL;

int slave_address = strtol(argv[1], nullptr, 0);
int register_address = strtol(argv[2], nullptr, 0);

for (int i = 0; i < num_bytes; i++) {
data[i] = strtol(argv[i + 3], nullptr, 0);
}

return i2c.write_payload(slave_address, register_address, data, num_bytes);

#else
return -1;
#endif
}

int i2c_read_payload(CommandRouter *cmd, int argc, const char **argv) {
#if TEENSY_TO_ANY_HAS_I2C
const int num_bytes_max = 8;
if (argc != 4)
return EINVAL;

int slave_address = strtol(argv[1], nullptr, 0);
int register_address = strtol(argv[2], nullptr, 0);
int num_bytes = strtol(argv[3], nullptr, 0);
if (num_bytes > num_bytes_max)
return EINVAL;

uint8_t data[8];
int result;
result = i2c.read_payload(slave_address, register_address, data, num_bytes);

if (result == 0) {
for (int i = 0; i < num_bytes; i++) {
if (i == 0) {
snprintf(cmd->buffer, cmd->buffer_size, "0x%02X", data[i]);
} else {
snprintf(cmd->buffer + strlen(cmd->buffer), cmd->buffer_size, "0x%02X",
data[i]);
}
if (i != num_bytes - 1) {
snprintf(cmd->buffer + strlen(cmd->buffer), cmd->buffer_size, "%c",
' ');
}
}
}
return result;
#else
return -1;
#endif
}

int i2c_read_uint16(CommandRouter *cmd, int argc, const char **argv) {
#if TEENSY_TO_ANY_HAS_I2C
if (argc != 3)
Expand Down

0 comments on commit e0cc1a8

Please sign in to comment.