M261 S I2C output format (#22890)

Co-authored-by: Scott Lahteine <github@thinkyhead.com>
This commit is contained in:
Stuart Pittaway 2021-10-11 23:42:29 +01:00 committed by Scott Lahteine
parent 64128a5bcb
commit f3be03da20
4 changed files with 64 additions and 16 deletions

View File

@ -28,11 +28,17 @@
#include <Wire.h> #include <Wire.h>
#include "../libs/hex_print.h"
TWIBus i2c; TWIBus i2c;
TWIBus::TWIBus() { TWIBus::TWIBus() {
#if I2C_SLAVE_ADDRESS == 0 #if I2C_SLAVE_ADDRESS == 0
Wire.begin(); // No address joins the BUS as the master Wire.begin( // No address joins the BUS as the master
#if PINS_EXIST(I2C_SCL, I2C_SDA) && DISABLED(SOFT_I2C_EEPROM)
pin_t(I2C_SDA_PIN), pin_t(I2C_SCL_PIN)
#endif
);
#else #else
Wire.begin(I2C_SLAVE_ADDRESS); // Join the bus as a slave Wire.begin(I2C_SLAVE_ADDRESS); // Join the bus as a slave
#endif #endif
@ -88,14 +94,53 @@ void TWIBus::echoprefix(uint8_t bytes, FSTR_P const pref, uint8_t adr) {
} }
// static // static
void TWIBus::echodata(uint8_t bytes, FSTR_P const pref, uint8_t adr) { void TWIBus::echodata(uint8_t bytes, FSTR_P const pref, uint8_t adr, const uint8_t style/*=0*/) {
echoprefix(bytes, pref, adr); union TwoBytesToInt16 { uint8_t bytes[2]; int16_t integervalue; };
while (bytes-- && Wire.available()) SERIAL_CHAR(Wire.read()); TwoBytesToInt16 ConversionUnion;
echoprefix(bytes, pref, adr);
while (bytes-- && Wire.available()) {
int value = Wire.read();
switch (style) {
// Style 1, HEX DUMP
case 1:
SERIAL_CHAR(hex_nybble((value & 0xF0) >> 4));
SERIAL_CHAR(hex_nybble(value & 0x0F));
if (bytes) SERIAL_CHAR(' ');
break;
// Style 2, signed two byte integer (int16)
case 2:
if (bytes == 1)
ConversionUnion.bytes[1] = (uint8_t)value;
else if (bytes == 0) {
ConversionUnion.bytes[0] = (uint8_t)value;
// Output value in base 10 (standard decimal)
SERIAL_ECHO(ConversionUnion.integervalue);
}
break;
// Style 3, unsigned byte, base 10 (uint8)
case 3:
SERIAL_ECHO(value);
if (bytes) SERIAL_CHAR(' ');
break;
// Default style (zero), raw serial output
default:
// This can cause issues with some serial consoles, Pronterface is an example where things go wrong
SERIAL_CHAR(value);
break;
}
}
SERIAL_EOL(); SERIAL_EOL();
} }
void TWIBus::echobuffer(FSTR_P const pref, uint8_t adr) { void TWIBus::echobuffer(FSTR_P const prefix, uint8_t adr) {
echoprefix(buffer_s, pref, adr); echoprefix(buffer_s, prefix, adr);
LOOP_L_N(i, buffer_s) SERIAL_CHAR(buffer[i]); LOOP_L_N(i, buffer_s) SERIAL_CHAR(buffer[i]);
SERIAL_EOL(); SERIAL_EOL();
} }
@ -114,11 +159,11 @@ bool TWIBus::request(const uint8_t bytes) {
return true; return true;
} }
void TWIBus::relay(const uint8_t bytes) { void TWIBus::relay(const uint8_t bytes, const uint8_t style/*=0*/) {
debug(F("relay"), bytes); debug(F("relay"), bytes);
if (request(bytes)) if (request(bytes))
echodata(bytes, F("i2c-reply"), addr); echodata(bytes, F("i2c-reply"), addr, style);
} }
uint8_t TWIBus::capture(char *dst, const uint8_t bytes) { uint8_t TWIBus::capture(char *dst, const uint8_t bytes) {

View File

@ -142,7 +142,7 @@ class TWIBus {
* *
* @param bytes the number of bytes to request * @param bytes the number of bytes to request
*/ */
static void echoprefix(uint8_t bytes, FSTR_P prefix, uint8_t adr); static void echoprefix(uint8_t bytes, FSTR_P const prefix, uint8_t adr);
/** /**
* @brief Echo data on the bus to serial * @brief Echo data on the bus to serial
@ -150,8 +150,9 @@ class TWIBus {
* to serial in a parser-friendly format. * to serial in a parser-friendly format.
* *
* @param bytes the number of bytes to request * @param bytes the number of bytes to request
* @param style Output format for the bytes, 0 = Raw byte [default], 1 = Hex characters, 2 = uint16_t
*/ */
static void echodata(uint8_t bytes, FSTR_P prefix, uint8_t adr); static void echodata(uint8_t bytes, FSTR_P const prefix, uint8_t adr, const uint8_t style=0);
/** /**
* @brief Echo data in the buffer to serial * @brief Echo data in the buffer to serial
@ -160,7 +161,7 @@ class TWIBus {
* *
* @param bytes the number of bytes to request * @param bytes the number of bytes to request
*/ */
void echobuffer(FSTR_P prefix, uint8_t adr); void echobuffer(FSTR_P const prefix, uint8_t adr);
/** /**
* @brief Request data from the slave device and wait. * @brief Request data from the slave device and wait.
@ -192,10 +193,11 @@ class TWIBus {
* @brief Request data from the slave device, echo to serial. * @brief Request data from the slave device, echo to serial.
* @details Request a number of bytes from a slave device and output * @details Request a number of bytes from a slave device and output
* the returned data to serial in a parser-friendly format. * the returned data to serial in a parser-friendly format.
* @style Output format for the bytes, 0 = raw byte [default], 1 = Hex characters, 2 = uint16_t
* *
* @param bytes the number of bytes to request * @param bytes the number of bytes to request
*/ */
void relay(const uint8_t bytes); void relay(const uint8_t bytes, const uint8_t style=0);
#if I2C_SLAVE_ADDRESS > 0 #if I2C_SLAVE_ADDRESS > 0

View File

@ -60,15 +60,16 @@ void GcodeSuite::M260() {
/** /**
* M261: Request X bytes from I2C slave device * M261: Request X bytes from I2C slave device
* *
* Usage: M261 A<slave device address base 10> B<number of bytes> * Usage: M261 A<slave device address base 10> B<number of bytes> S<style>
*/ */
void GcodeSuite::M261() { void GcodeSuite::M261() {
if (parser.seen('A')) i2c.address(parser.value_byte()); if (parser.seen('A')) i2c.address(parser.value_byte());
uint8_t bytes = parser.byteval('B', 1); const uint8_t bytes = parser.byteval('B', 1), // Bytes to request
style = parser.byteval('S'); // Serial output style (ASCII, HEX etc)
if (i2c.addr && bytes && bytes <= TWIBUS_BUFFER_SIZE) if (i2c.addr && bytes && bytes <= TWIBUS_BUFFER_SIZE)
i2c.relay(bytes); i2c.relay(bytes, style);
else else
SERIAL_ERROR_MSG("Bad i2c request"); SERIAL_ERROR_MSG("Bad i2c request");
} }

View File

@ -27,7 +27,7 @@
// Utility functions to create and print hex strings as nybble, byte, and word. // Utility functions to create and print hex strings as nybble, byte, and word.
// //
FORCE_INLINE char hex_nybble(const uint8_t n) { constexpr char hex_nybble(const uint8_t n) {
return (n & 0xF) + ((n & 0xF) < 10 ? '0' : 'A' - 10); return (n & 0xF) + ((n & 0xF) < 10 ? '0' : 'A' - 10);
} }
char* hex_byte(const uint8_t b); char* hex_byte(const uint8_t b);