aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/feature/twibus.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Marlin/src/feature/twibus.cpp')
-rw-r--r--Marlin/src/feature/twibus.cpp190
1 files changed, 190 insertions, 0 deletions
diff --git a/Marlin/src/feature/twibus.cpp b/Marlin/src/feature/twibus.cpp
new file mode 100644
index 0000000..855a318
--- /dev/null
+++ b/Marlin/src/feature/twibus.cpp
@@ -0,0 +1,190 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../inc/MarlinConfig.h"
+
+#if ENABLED(EXPERIMENTAL_I2CBUS)
+
+#include "twibus.h"
+
+#include <Wire.h>
+
+TWIBus i2c;
+
+TWIBus::TWIBus() {
+ #if I2C_SLAVE_ADDRESS == 0
+ Wire.begin(); // No address joins the BUS as the master
+ #else
+ Wire.begin(I2C_SLAVE_ADDRESS); // Join the bus as a slave
+ #endif
+ reset();
+}
+
+void TWIBus::reset() {
+ buffer_s = 0;
+ buffer[0] = 0x00;
+}
+
+void TWIBus::address(const uint8_t adr) {
+ if (!WITHIN(adr, 8, 127)) {
+ SERIAL_ECHO_MSG("Bad I2C address (8-127)");
+ }
+
+ addr = adr;
+
+ debug(PSTR("address"), adr);
+}
+
+void TWIBus::addbyte(const char c) {
+ if (buffer_s >= COUNT(buffer)) return;
+ buffer[buffer_s++] = c;
+ debug(PSTR("addbyte"), c);
+}
+
+void TWIBus::addbytes(char src[], uint8_t bytes) {
+ debug(PSTR("addbytes"), bytes);
+ while (bytes--) addbyte(*src++);
+}
+
+void TWIBus::addstring(char str[]) {
+ debug(PSTR("addstring"), str);
+ while (char c = *str++) addbyte(c);
+}
+
+void TWIBus::send() {
+ debug(PSTR("send"), addr);
+
+ Wire.beginTransmission(I2C_ADDRESS(addr));
+ Wire.write(buffer, buffer_s);
+ Wire.endTransmission();
+
+ reset();
+}
+
+// static
+void TWIBus::echoprefix(uint8_t bytes, const char pref[], uint8_t adr) {
+ SERIAL_ECHO_START();
+ serialprintPGM(pref);
+ SERIAL_ECHOPAIR(": from:", adr, " bytes:", bytes, " data:");
+}
+
+// static
+void TWIBus::echodata(uint8_t bytes, const char pref[], uint8_t adr) {
+ echoprefix(bytes, pref, adr);
+ while (bytes-- && Wire.available()) SERIAL_CHAR(Wire.read());
+ SERIAL_EOL();
+}
+
+void TWIBus::echobuffer(const char pref[], uint8_t adr) {
+ echoprefix(buffer_s, pref, adr);
+ LOOP_L_N(i, buffer_s) SERIAL_CHAR(buffer[i]);
+ SERIAL_EOL();
+}
+
+bool TWIBus::request(const uint8_t bytes) {
+ if (!addr) return false;
+
+ debug(PSTR("request"), bytes);
+
+ // requestFrom() is a blocking function
+ if (Wire.requestFrom(I2C_ADDRESS(addr), bytes) == 0) {
+ debug("request fail", I2C_ADDRESS(addr));
+ return false;
+ }
+
+ return true;
+}
+
+void TWIBus::relay(const uint8_t bytes) {
+ debug(PSTR("relay"), bytes);
+
+ if (request(bytes))
+ echodata(bytes, PSTR("i2c-reply"), addr);
+}
+
+uint8_t TWIBus::capture(char *dst, const uint8_t bytes) {
+ reset();
+ uint8_t count = 0;
+ while (count < bytes && Wire.available())
+ dst[count++] = Wire.read();
+
+ debug(PSTR("capture"), count);
+
+ return count;
+}
+
+// static
+void TWIBus::flush() {
+ while (Wire.available()) Wire.read();
+}
+
+#if I2C_SLAVE_ADDRESS > 0
+
+ void TWIBus::receive(uint8_t bytes) {
+ debug(PSTR("receive"), bytes);
+ echodata(bytes, PSTR("i2c-receive"), 0);
+ }
+
+ void TWIBus::reply(char str[]/*=nullptr*/) {
+ debug(PSTR("reply"), str);
+
+ if (str) {
+ reset();
+ addstring(str);
+ }
+
+ Wire.write(buffer, buffer_s);
+
+ reset();
+ }
+
+ void i2c_on_receive(int bytes) { // just echo all bytes received to serial
+ i2c.receive(bytes);
+ }
+
+ void i2c_on_request() { // just send dummy data for now
+ i2c.reply("Hello World!\n");
+ }
+
+#endif
+
+#if ENABLED(DEBUG_TWIBUS)
+
+ // static
+ void TWIBus::prefix(const char func[]) {
+ SERIAL_ECHOPGM("TWIBus::");
+ serialprintPGM(func);
+ SERIAL_ECHOPGM(": ");
+ }
+ void TWIBus::debug(const char func[], uint32_t adr) {
+ if (DEBUGGING(INFO)) { prefix(func); SERIAL_ECHOLN(adr); }
+ }
+ void TWIBus::debug(const char func[], char c) {
+ if (DEBUGGING(INFO)) { prefix(func); SERIAL_ECHOLN(c); }
+ }
+ void TWIBus::debug(const char func[], char str[]) {
+ if (DEBUGGING(INFO)) { prefix(func); SERIAL_ECHOLN(str); }
+ }
+
+#endif
+
+#endif // EXPERIMENTAL_I2CBUS