// // A "console" to intereact via USB serial with the I2C bus. // #include // for isxdigit() #include static enum { PRINT_MENU, WAIT_FOR_OP, WAIT_FOR_ADDR1, // first nibble WAIT_FOR_ADDR2, // second nibble // When reading: WAIT_FOR_COUNT, // When writing: WAIT_FOR_BYTES1, // first nibble WAIT_FOR_BYTES2, // second nibble } state = PRINT_MENU; #define I2C_RETRIES 3 // how many times we should attempt an I2C operation // Convert a VALID hex character to an integer [0..15] static uint8_t h2i(int c) { if (c >= 'a') return (c - 'a') + 10; if (c >= 'A') return (c - 'A') + 10; return c - '0'; } static void read_i2c(uint8_t address, uint8_t num_bytes) { Serial.print("\n\rREADING FROM "); Serial.print(address, HEX); Serial.print("; "); Serial.print(num_bytes); Serial.println(" bytes"); uint8_t retries = I2C_RETRIES; uint8_t result; do { result = Wire.requestFrom(address, num_bytes, (uint8_t)true); Serial.print(" read["); Serial.print(retries); Serial.print("] "); Serial.print(result); Serial.print(" bytes: "); int value; while ((value = Wire.read()) != -1) { Serial.print(value, HEX); } Serial.println(); } while (result != num_bytes && --retries > 0); } static void write_i2c(uint8_t address, uint8_t num_bytes, const uint8_t bytes[]) { Serial.print("\n\rWRITING TO "); Serial.print(address, HEX); Serial.print("; "); Serial.print(num_bytes); Serial.print(" bytes: "); for (int i = 0; i < num_bytes; ++i) { Serial.print(bytes[i], HEX); } Serial.println(); uint8_t retries = I2C_RETRIES; uint8_t result; static const char * const errstr[6] = { "success", "length too long for buffer", "address sent, NACK observed", "data sent, NACK observed", "unknown error", "timeout", }; do { Serial.print(" writing["); Serial.print(retries); Serial.print("]... "); // WRITE to a SLAVE. Wire.beginTransmission(address); Wire.write(bytes, num_bytes); result = Wire.endTransmission(true); if (result == 0) { Serial.println("success"); } else if (result < sizeof(errstr)) { Serial.print("ERROR: ["); Serial.print(result); Serial.print("] "); Serial.println(errstr[result]); } else { Serial.print("ERROR: out of range: "); Serial.println(result); } } while (result != 0 && --retries > 0); } void setup() { Serial.begin(9600); Wire.begin(); // no address. we are only a MASTER. } void loop() { static bool op_is_read; static uint8_t address; static uint8_t bufsize; static uint8_t buf[10]; if (state == PRINT_MENU) { Serial.print("MENU:\n\r" " r,R: read from I2C bus\n\r" " w,W: write to I2C bus\n\r" "Operation? "); state = WAIT_FOR_OP; } char c = Serial.read(); if (c == -1) return; // nothing available //Serial.print("{"); Serial.print(state); Serial.print("}"); switch (state) { case WAIT_FOR_OP: Serial.print(c); if (c == 'r' || c == 'R') { op_is_read = true; Serial.print("\n\r[READ] ADDRESS (2 hex digits)? "); state = WAIT_FOR_ADDR1; } else if (c == 'w' || c == 'W') { op_is_read = false; Serial.print("\n\r[WRITE] ADDRESS (2 hex digits)? "); state = WAIT_FOR_ADDR1; } else { Serial.println("\n\rERROR: unknown operation"); state = PRINT_MENU; } return; case WAIT_FOR_ADDR1: Serial.print(c); if (!isxdigit(c)) goto bad_hex; address = h2i(c) * 16; state = WAIT_FOR_ADDR2; return; case WAIT_FOR_ADDR2: Serial.print(c); if (!isxdigit(c)) goto bad_hex; address += h2i(c); if (op_is_read) { Serial.print("\n\r[READ] COUNT (single digit)? "); state = WAIT_FOR_COUNT; } else { bufsize = 0; Serial.print("\n\r[WRITE] CONTENT (hex digit pairs; CR): "); state = WAIT_FOR_BYTES1; } return; case WAIT_FOR_COUNT: Serial.print(c); if (!isdigit(c)) { Serial.println("\n\rERROR: bad digit"); state = PRINT_MENU; return; } read_i2c(address, c - '0'); state = PRINT_MENU; return; case WAIT_FOR_BYTES1: Serial.print(c); if (c == '\r') { write_i2c(address, bufsize, buf); state = PRINT_MENU; return; } if (!isxdigit(c)) goto bad_hex; buf[bufsize] = h2i(c) * 16; state = WAIT_FOR_BYTES2; return; case WAIT_FOR_BYTES2: Serial.print(c); if (!isxdigit(c)) goto bad_hex; buf[bufsize++] += h2i(c); state = WAIT_FOR_BYTES1; return; default: Serial.println("\n\rERROR: unknown state"); state = PRINT_MENU; return; } /* NOTREACHED */ return; Serial.print("Saw: '"); Serial.print(c, HEX); Serial.print("'\n\r"); return; bad_hex: Serial.println("\n\rERROR: bad hex digit"); state = PRINT_MENU; return; }