diff --git a/I2CManager_SAMD.h b/I2CManager_SAMD.h
new file mode 100644
index 0000000..aeabd6c
--- /dev/null
+++ b/I2CManager_SAMD.h
@@ -0,0 +1,188 @@
+/*
+ * © 2021, Neil McKechnie. All rights reserved.
+ *
+ * This file is part of CommandStation-EX
+ *
+ * This 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.
+ *
+ * It 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 CommandStation. If not, see .
+ */
+
+#ifndef I2CMANAGER_SAMD_H
+#define I2CMANAGER_SAMD_H
+
+#include
+#include "I2CManager.h"
+
+//#include
+//#include
+
+#if defined(I2C_USE_INTERRUPTS) && defined(ARDUINO_SAMD_ZERO)
+// PMA - IRQ handler, based on SERCOM3 being used for I2C, as per Arduino Zero & Sparkfun SAMD21
+// TODO: test
+void SERCOM3_Handler() {
+ I2CManagerClass::handleInterrupt();
+}
+#endif
+
+/***************************************************************************
+ * Set I2C clock speed register.
+ ***************************************************************************/
+void I2CManagerClass::I2C_setClock(unsigned long i2cClockSpeed) {
+ unsigned long temp = ((F_CPU / i2cClockSpeed) - 16) / 2;
+ for (uint8_t preScaler = 0; preScaler<=3; preScaler++) {
+ if (temp <= 255) {
+ TWBR = temp;
+ TWSR = (TWSR & 0xfc) | preScaler;
+ return;
+ } else
+ temp /= 4;
+ }
+ // Set slowest speed ~= 500 bits/sec
+ TWBR = 255;
+ TWSR |= 0x03;
+}
+
+/***************************************************************************
+ * Initialise I2C registers.
+ ***************************************************************************/
+void I2CManagerClass::I2C_init()
+{
+ // PMA - broadly we do the following
+ initialise the clock
+ initialise the NVIC
+ software reset the I2C for the sercom
+ set master mode
+ do we need smart mode and quick command??
+ configure interrupt handlers
+ enable interrupts
+ set default baud rate
+ set SDA/SCL pins as outputs and enable pullups
+}
+
+/***************************************************************************
+ * Initiate a start bit for transmission.
+ ***************************************************************************/
+void I2CManagerClass::I2C_sendStart() {
+ bytesToSend = currentRequest->writeLen;
+ bytesToReceive = currentRequest->readLen;
+ // We may have initiated a stop bit before this without waiting for it.
+ // Wait for stop bit to be sent before sending start.
+ while (TWCR & (1<writeBuffer + (txCount++));
+ else
+ TWDR = currentRequest->writeBuffer[txCount++];
+ bytesToSend--;
+ TWCR = (1< 0) {
+ currentRequest->readBuffer[rxCount++] = TWDR;
+ bytesToReceive--;
+ }
+ /* fallthrough */
+ case TWI_MRX_ADR_ACK: // SLA+R has been sent and ACK received
+ if (bytesToReceive <= 1) {
+ TWCR = (1< 0) {
+ currentRequest->readBuffer[rxCount++] = TWDR;
+ bytesToReceive--;
+ }
+ TWCR = (1<i2cAddress << 1) | 1; // SLA+R
+ else
+ TWDR = (currentRequest->i2cAddress << 1) | 0; // SLA+W
+ TWCR = (1<