 uint8_t const TWSR_REP_START = 0x10;
 uint8_t const I2C_READ = 1;
 uint8_t const I2C_WRITE = 0;
+#endif
 
 void I2Cinit(bool enablePullup) {
+#if defined(__AVR_ATmega4809__) || defined(__AVR_ATtiny3216__)
+  if (enablePullup) {
+    pinMode(PIN_WIRE_SDA, INPUT_PULLUP);
+    pinMode(PIN_WIRE_SCL, INPUT_PULLUP);
+  }
+  uint32_t baud = ((F_CPU_CORRECTED/FREQUENCY) - (((F_CPU_CORRECTED*T_RISE)/1000)/1000)/1000 - 10)/2;
+  TWI0.MBAUD = (uint8_t)baud;
+  TWI0.MCTRLA = TWI_ENABLE_bm;                                        // Enable as master, no interrupts
+  TWI0.MSTATUS = TWI_BUSSTATE_IDLE_gc;
+#else
   TWSR = 0;                        // no prescaler
   TWBR = (F_CPU/F_TWI - 16)/2;     // set bit rate factor
   if (enablePullup) {
     digitalWrite(TWI_SDA_PIN, HIGH);
     digitalWrite(TWI_SCL_PIN, HIGH);
   }
-}
-
-uint8_t I2Cread() {
+#endif
+}
+
+int I2Cread() {
+#if defined(__AVR_ATmega4809__) || defined(__AVR_ATtiny3216__)
+  if (I2CCount != 0) I2CCount--;
+  while (!(TWI0.MSTATUS & TWI_RIF_bm));                               // Wait for read interrupt flag
+  uint8_t data = TWI0.MDATA;
+  // Check slave sent ACK?
+  if (I2CCount != 0) TWI0.MCTRLB = TWI_MCMD_RECVTRANS_gc;             // ACK = more bytes to read
+  else TWI0.MCTRLB = TWI_ACKACT_bm | TWI_MCMD_RECVTRANS_gc;           // Send NAK
+  return data;
+#else
   if (I2CCount != 0) I2CCount--;
   TWCR = 1<<TWINT | 1<<TWEN | ((I2CCount == 0) ? 0 : (1<<TWEA));
   while (!(TWCR & 1<<TWINT));
   return TWDR;
+#endif
 }
 
 bool I2Cwrite(uint8_t data) {
+#if defined(__AVR_ATmega4809__) || defined(__AVR_ATtiny3216__)
+  while (!(TWI0.MSTATUS & TWI_WIF_bm));                               // Wait for write interrupt flag
+  TWI0.MDATA = data;
+  TWI0.MCTRLB = TWI_MCMD_RECVTRANS_gc;                                // Do nothing
+  return !(TWI0.MSTATUS & TWI_RXACK_bm);                              // Returns true if slave gave an ACK
+#else
   TWDR = data;
   TWCR = 1<<TWINT | 1 << TWEN;
   while (!(TWCR & 1<<TWINT));
   return (TWSR & 0xF8) == TWSR_MTX_DATA_ACK;
+#endif
 }
 
 bool I2Cstart(uint8_t address, uint8_t read) {
+#if defined(__AVR_ATmega4809__) || defined(__AVR_ATtiny3216__)
+  TWI0.MADDR = address<<1 | read;                                     // Send START condition
+  while (!(TWI0.MSTATUS & (TWI_WIF_bm | TWI_RIF_bm)));                // Wait for write or read interrupt flag
+  if ((TWI0.MSTATUS & TWI_ARBLOST_bm)) return false;                  // Return false if arbitration lost or bus error
+  return !(TWI0.MSTATUS & TWI_RXACK_bm);                              // Return true if slave gave an ACK
+#else
   uint8_t addressRW = address<<1 | read;
-  TWCR = 1<<TWINT | 1<<TWSTA | 1<<TWEN;    // send START condition
+  TWCR = 1<<TWINT | 1<<TWSTA | 1<<TWEN;    // Send START condition
   while (!(TWCR & 1<<TWINT));
   if ((TWSR & 0xF8) != TWSR_START && (TWSR & 0xF8) != TWSR_REP_START) return false;
   TWDR = addressRW;  // send device address and direction

      args = cdr(args);
    }
  }
}

object *sp_push (object *args, object *env) {


typedef int (*gfun_t)();
typedef void (*pfun_t)(char);
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__)
typedef int BitOrder;
typedef int PinMode;
#endif

// Workspace - sizes in bytes
#define WORDALIGNED __attribute__((aligned (2)))
#define BUFFERSIZE 18

#if defined(__AVR_ATmega328P__)
#define WORKSPACESIZE 315-SDSIZE        /* Objects (4*bytes) */
#define EEPROMSIZE 1024                 /* Bytes */
#define SYMBOLTABLESIZE BUFFERSIZE      /* Bytes - no long symbols */

#elif defined(__AVR_ATmega2560__)
#define WORKSPACESIZE 1214-SDSIZE       /* Objects (4*bytes) */
#define EEPROMSIZE 4096                 /* Bytes */
#define SYMBOLTABLESIZE 512             /* Bytes */

#elif defined(__AVR_ATmega1284P__)
#define WORKSPACESIZE 2816-SDSIZE       /* Objects (4*bytes) */
#define EEPROMSIZE 4096                 /* Bytes */
#define SYMBOLTABLESIZE 512             /* Bytes */

#elif defined(ARDUINO_AVR_NANO_EVERY)
#define WORKSPACESIZE 1068-SDSIZE       /* Objects (4*bytes) */
#define EEPROMSIZE 256                  /* Bytes */
#define SYMBOLTABLESIZE BUFFERSIZE      /* Bytes - no long symbols */

#elif defined(__AVR_ATmega4809__)
#define WORKSPACESIZE 1068-SDSIZE       /* Objects (4*bytes) */
#define EEPROMSIZE 256                  /* Bytes */
#define SYMBOLTABLESIZE BUFFERSIZE      /* Bytes - no long symbols */

#elif defined(__AVR_ATtiny3216__)
#define WORKSPACESIZE 306-SDSIZE        /* Objects (4*bytes) */
#define EEPROMSIZE 256                  /* Bytes */
#define SYMBOLTABLESIZE BUFFERSIZE      /* Bytes - no long symbols */

#endif

object Workspace[WORKSPACESIZE] WORDALIGNED;
char SymbolTable[SYMBOLTABLESIZE];
#define SDCARD_SS_PIN 10

// Global variables
