I2C_Commands.cpp 3.64 KB
/*
 * CLI_I2C_Commands.cpp - CLI library for Arduino/ESP8266 - I2C Commands implementation
 *
 * Version 1.0, latest version, documentation and bugtracker available at:
 *              https://gitlab.lindenaar.net/arduino/CLI
 *
 * Copyright (c) 2019 Frederik Lindenaar
 *
 * This library is free software: you can redistribute it and/or modify it under
 * the terms of version 3 of the GNU General Public License as published by the
 * Free Software Foundation, or (at your option) a later version of the license.
 *
 * This code is distributed in the hope that it will be useful but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, visit <http://www.gnu.org/licenses/> to download it.
 */

#include <CLI.h>
#include <Wire.h>

I2C_Scan_Command::I2C_Scan_Command(CLI & cli) : CLI_Command(cli,
      PSTR("i2c_scan"), PSTR("Scan I2C bus for slave devices")) { };

bool I2C_Scan_Command::setparams(const char *params) {
  _address = _found = 0;
  return !params;
}

bool I2C_Scan_Command::execute(CLI &cli) {
  if (_address < 127) {
    if (_address == 0) cli.println(F("Scanning I2C..."));
    Wire.beginTransmission(_address);
    uint8_t error = Wire.endTransmission();

    if (error == 0) {
      cli.print(F("I2C device found at address 0x"));
      if (_address < 0x10) cli.print("0");
      cli.println(_address, HEX);
      _found++;
    } else if (error == 4) {
      cli.print(F("Unknown error at address 0x"));
      if (_address < 0x10) cli.print("0");
      cli.println(_address, HEX);
    }
    _address++;
    return true;
  } else {
    if (_found == 0)
      cli.print_P(PSTR("No I2C devices found"));
    return false;
  }
}


I2C_Dump_Command::I2C_Dump_Command(CLI & cli) : CLI_Command(cli,
      PSTR("i2c_dump"), PSTR("Display I2C EEPROM/Memory in HEX and ASCII"),
      PSTR("Usage: i2c_dump 0x<id> <size> [<skip>] [single]\n"
           "where:\t<id>\tHEX I2C device ID\n"
                 "\t<size>\tsize of memory\n"
                 "\t<skip>\t(optional) start offset\n"
                 "\tsingle\tto enforce 1-byte addressing")) { };

bool I2C_Dump_Command::setparams(const char *params) {
  if (params && *(params++) == '0' && *(params++) == 'x') {
    if ((params = CLI_STR_parse_HEX_byte(params, _address)) && *params == ' ') {
      if(params = CLI_STR_parseInt(CLI_STR_skipSep(params), (int &)_length)) {
        _offset = 0;
        _large = _length > 0xff;
        if (*params == ' ') {
          params = CLI_STR_skipSep(params);
          if(const char *p = CLI_STR_parseInt(params, (int &)_offset))
            params = CLI_STR_skipSep(p);
          if (strcmp_P(params, PSTR("single")) == 0) {
            if (_large) return false;
            params += 6;
          }
        }
        return *params == 0;
      }
    }
  }
  return false;
}

bool I2C_Dump_Command::execute(CLI &cli) {
  uint8_t buffer[16], len = 0;

  Wire.beginTransmission(_address);
  if (_large) Wire.write((uint8_t)(_offset >> 8));   // MSB
  Wire.write((uint8_t)(_offset & 0xff));  // LSB
  if (Wire.endTransmission() != 0) {
    cli.print(F("No I2C device at 0x"));
    cli.print(_address, HEX);
    cli.println();
    return false;
  }

  if (_offset == 0) cli.println(F("I2C EEPROM/Memory: "));

  Wire.requestFrom(_address, (uint8_t) (_length - _offset < sizeof(buffer)) ? _length - _offset : sizeof(buffer));
  while (Wire.available() && len < sizeof(buffer)) buffer[len++] = Wire.read();

  cli.print_mem(_offset, buffer, len);
  _offset += len;
  return _offset < _length;
}