Skip to content
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

Output formatting of M261 i2c command #22890

Merged
merged 4 commits into from
Oct 11, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
61 changes: 53 additions & 8 deletions Marlin/src/feature/twibus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,17 @@

#include <Wire.h>

#include "../libs/hex_print.h"

TWIBus i2c;

TWIBus::TWIBus() {
#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
Wire.begin(I2C_SLAVE_ADDRESS); // Join the bus as a slave
#endif
Expand Down Expand Up @@ -88,14 +94,53 @@ void TWIBus::echoprefix(uint8_t bytes, FSTR_P const pref, uint8_t adr) {
}

// static
void TWIBus::echodata(uint8_t bytes, FSTR_P const pref, uint8_t adr) {
echoprefix(bytes, pref, adr);
while (bytes-- && Wire.available()) SERIAL_CHAR(Wire.read());
void TWIBus::echodata(uint8_t bytes, FSTR_P const pref, uint8_t adr, const uint8_t style/*=0*/) {
union TwoBytesToInt16 { uint8_t bytes[2]; int16_t integervalue; };
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();
}

void TWIBus::echobuffer(FSTR_P const pref, uint8_t adr) {
echoprefix(buffer_s, pref, adr);
void TWIBus::echobuffer(FSTR_P const prefix, uint8_t adr) {
echoprefix(buffer_s, prefix, adr);
LOOP_L_N(i, buffer_s) SERIAL_CHAR(buffer[i]);
SERIAL_EOL();
}
Expand All @@ -114,11 +159,11 @@ bool TWIBus::request(const uint8_t bytes) {
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);

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) {
Expand Down
10 changes: 6 additions & 4 deletions Marlin/src/feature/twibus.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,17 @@ class TWIBus {
*
* @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
* @details Echo some number of bytes from the bus
* to serial in a parser-friendly format.
*
* @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
Expand All @@ -160,7 +161,7 @@ class TWIBus {
*
* @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.
Expand Down Expand Up @@ -192,10 +193,11 @@ class TWIBus {
* @brief Request data from the slave device, echo to serial.
* @details Request a number of bytes from a slave device and output
* 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
*/
void relay(const uint8_t bytes);
void relay(const uint8_t bytes, const uint8_t style=0);

#if I2C_SLAVE_ADDRESS > 0

Expand Down
7 changes: 4 additions & 3 deletions Marlin/src/gcode/feature/i2c/M260_M261.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,16 @@ void GcodeSuite::M260() {
/**
* 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() {
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)
i2c.relay(bytes);
i2c.relay(bytes, style);
else
SERIAL_ERROR_MSG("Bad i2c request");
}
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/libs/hex_print.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
// 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);
}
char* hex_byte(const uint8_t b);
Expand Down