diff --git a/bootloaders/zero/board_driver_i2c.c b/bootloaders/zero/board_driver_i2c.c
index a83fccf03fbd59653c6e94259f84370e016a8926..c7d73deb671796dd3958c84de014dc6d4495a0bb 100644
--- a/bootloaders/zero/board_driver_i2c.c
+++ b/bootloaders/zero/board_driver_i2c.c
@@ -18,31 +18,55 @@
 */
 
 #include "board_driver_i2c.h"
+#include "board_driver_led.h"
 
 #ifdef CONFIGURE_PMIC
 
 /*- Definitions -------------------------------------------------------------*/
-#define I2C_SERCOM            SERCOM2
-#define I2C_SERCOM_PMUX       PORT_PMUX_PMUXE_D_Val
-#define I2C_SERCOM_GCLK_ID    SERCOM0_GCLK_ID_CORE
+#define I2C_SERCOM            SERCOM0
+#define I2C_SERCOM_GCLK_ID    GCLK_CLKCTRL_ID_SERCOM0_CORE_Val
 #define I2C_SERCOM_CLK_GEN    0
 #define I2C_SERCOM_APBCMASK   PM_APBCMASK_SERCOM0
 
-#define T_RISE                215e-9 // Depends on the board, actually
+static uint8_t txBuffer[2];
+static uint8_t rxBuffer[1];
+static uint8_t txBufferLen = 0;
+static uint8_t rxBufferLen = 0;
+static uint8_t txAddress;
 
-enum
+typedef enum
 {
-  I2C_TRANSFER_WRITE = 0,
-  I2C_TRANSFER_READ  = 1,
-};
+  WIRE_UNKNOWN_STATE = 0x0ul,
+  WIRE_IDLE_STATE,
+  WIRE_OWNER_STATE,
+  WIRE_BUSY_STATE
+} SercomWireBusState;
 
-enum
+typedef enum
 {
-  I2C_PINS_SDA = (1 << 0),
-  I2C_PINS_SCL = (1 << 1),
-};
+  WIRE_WRITE_FLAG = 0x0ul,
+  WIRE_READ_FLAG
+} SercomWireReadWriteFlag;
 
-#define F_CPU   48000000
+typedef enum
+{
+  WIRE_MASTER_ACT_NO_ACTION = 0,
+  WIRE_MASTER_ACT_REPEAT_START,
+  WIRE_MASTER_ACT_READ,
+  WIRE_MASTER_ACT_STOP
+} SercomMasterCommandWire;
+
+typedef enum
+{
+  WIRE_MASTER_ACK_ACTION = 0,
+  WIRE_MASTER_NACK_ACTION
+} SercomMasterAckActionWire;
+
+typedef enum
+{
+  I2C_SLAVE_OPERATION = 0x4u,
+  I2C_MASTER_OPERATION = 0x5u
+} SercomI2CMode;
 
 static inline void pin_set_peripheral_function(uint32_t pinmux)
 {
@@ -68,136 +92,356 @@ static inline void pin_set_peripheral_function(uint32_t pinmux)
     PORT->Group[port].PMUX[pin/2].reg |=  ( (uint8_t)( (pinmux&0xFFFF) <<(4*(pin&1)) ) ); 
 }
 
-//-----------------------------------------------------------------------------
-void i2c_init(int freq)
+static inline void initClockNVIC( void )
 {
+  //Setting clock
+  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( I2C_SERCOM_GCLK_ID ) | // Generic Clock 0 (SERCOMx)
+                      GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
+                      GCLK_CLKCTRL_CLKEN ;
 
-  PM->APBCMASK.reg |= I2C_SERCOM_APBCMASK;
+  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+  {
+    /* Wait for synchronization */
+  }
+  PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0;
+}
 
-  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(I2C_SERCOM_GCLK_ID) |
-      GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(I2C_SERCOM_CLK_GEN);
+static inline bool isBusIdleWIRE( void )
+{
+  return I2C_SERCOM->I2CM.STATUS.bit.BUSSTATE == WIRE_IDLE_STATE;
+}
 
-  I2C_SERCOM->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_SWRST;
-  while (I2C_SERCOM->I2CM.CTRLA.reg & SERCOM_I2CM_CTRLA_SWRST);
+static inline bool isBusOwnerWIRE( void )
+{
+  return I2C_SERCOM->I2CM.STATUS.bit.BUSSTATE == WIRE_OWNER_STATE;
+}
 
-  I2C_SERCOM->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;
-  while (I2C_SERCOM->I2CM.SYNCBUSY.reg);
+static inline bool isDataReadyWIRE( void )
+{
+  return I2C_SERCOM->I2CS.INTFLAG.bit.DRDY;
+}
 
-  I2C_SERCOM->I2CM.BAUD.reg = SERCOM_I2CM_BAUD_BAUD(48);
-  while (I2C_SERCOM->I2CM.SYNCBUSY.reg);
+static inline bool isStopDetectedWIRE( void )
+{
+  return I2C_SERCOM->I2CS.INTFLAG.bit.PREC;
+}
 
-  I2C_SERCOM->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_ENABLE |
-      SERCOM_I2CM_CTRLA_MODE_I2C_MASTER |
-      SERCOM_I2CM_CTRLA_SDAHOLD(3);
-  while (I2C_SERCOM->I2CM.SYNCBUSY.reg);
+static inline bool isRestartDetectedWIRE( void )
+{
+  return I2C_SERCOM->I2CS.STATUS.bit.SR;
+}
 
-  I2C_SERCOM->I2CM.STATUS.reg |= SERCOM_I2CM_STATUS_BUSSTATE(1);
+static inline bool isAddressMatch( void )
+{
+  return I2C_SERCOM->I2CS.INTFLAG.bit.AMATCH;
+}
 
-  pin_set_peripheral_function(PINMUX_PA08C_SERCOM0_PAD0);
-  pin_set_peripheral_function(PINMUX_PA09C_SERCOM0_PAD1);
+static inline bool isMasterReadOperationWIRE( void )
+{
+  return I2C_SERCOM->I2CS.STATUS.bit.DIR;
 }
 
-//-----------------------------------------------------------------------------
-bool i2c_start(int addr)
+static inline bool isRXNackReceivedWIRE( void )
 {
-  I2C_SERCOM->I2CM.ADDR.reg = addr;
+  return I2C_SERCOM->I2CM.STATUS.bit.RXNACK;
+}
 
-  while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB) &&
-         0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB));
+static inline int availableWIRE( void )
+{
+  return I2C_SERCOM->I2CM.INTFLAG.bit.SB;
+}
 
-  if (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK)
+static inline uint8_t readDataWIRE( void )
+{
+  while( I2C_SERCOM->I2CM.INTFLAG.bit.SB == 0 )
   {
-    I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
-    return false;
+    // Waiting complete receive
   }
 
-  return true;
+  return I2C_SERCOM->I2CM.DATA.bit.DATA ;
 }
 
-//-----------------------------------------------------------------------------
-bool i2c_stop(void)
+/*  =========================
+ *  ===== Sercom WIRE
+ *  =========================
+ */
+static inline void resetWIRE()
 {
-  if ((I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB) ||
-      (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB))
+  //I2CM OR I2CS, no matter SWRST is the same bit.
+
+  //Setting the Software bit to 1
+  I2C_SERCOM->I2CM.CTRLA.bit.SWRST = 1;
+
+  //Wait both bits Software Reset from CTRLA and SYNCBUSY are equal to 0
+  while(I2C_SERCOM->I2CM.CTRLA.bit.SWRST || I2C_SERCOM->I2CM.SYNCBUSY.bit.SWRST);
+}
+
+static inline void enableWIRE()
+{
+  // I2C Master and Slave modes share the ENABLE bit function.
+
+  // Enable the I²C master mode
+  I2C_SERCOM->I2CM.CTRLA.bit.ENABLE = 1 ;
+
+  while ( I2C_SERCOM->I2CM.SYNCBUSY.bit.ENABLE != 0 )
   {
-    I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
+    // Waiting the enable bit from SYNCBUSY is equal to 0;
   }
 
-  return true;
+  // Setting bus idle mode
+  I2C_SERCOM->I2CM.STATUS.bit.BUSSTATE = 1 ;
+
+  while ( I2C_SERCOM->I2CM.SYNCBUSY.bit.SYSOP != 0 )
+  {
+    // Wait the SYSOP bit from SYNCBUSY coming back to 0
+  }
 }
 
-//-----------------------------------------------------------------------------
-bool i2c_read_byte(uint8_t *byte, bool last)
+static inline void disableWIRE()
 {
-  while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB));
+  // I2C Master and Slave modes share the ENABLE bit function.
 
-  if (last)
-    I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT | SERCOM_I2CM_CTRLB_CMD(3);
-  else
-    I2C_SERCOM->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
+  // Enable the I²C master mode
+  I2C_SERCOM->I2CM.CTRLA.bit.ENABLE = 0 ;
+
+  while ( I2C_SERCOM->I2CM.SYNCBUSY.bit.ENABLE != 0 )
+  {
+    // Waiting the enable bit from SYNCBUSY is equal to 0;
+  }
+}
 
-  *byte = I2C_SERCOM->I2CM.DATA.reg;
+static inline void initMasterWIRE( uint32_t baudrate )
+{
+  // Initialize the peripheral clock and interruption
+  initClockNVIC() ;
+
+  //NVIC_EnableIRQ(SERCOM0_IRQn);
+  //NVIC_SetPriority (SERCOM0_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority */
+
+  resetWIRE() ;
+
+  // Set master mode and enable SCL Clock Stretch mode (stretch after ACK bit)
+  I2C_SERCOM->I2CM.CTRLA.reg =  SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION )/* |
+                            SERCOM_I2CM_CTRLA_SCLSM*/ ;
+
+  // Enable Smart mode and Quick Command
+  //I2C_SERCOM->I2CM.I2CM.CTRLB.reg =  SERCOM_I2CM_CTRLB_SMEN /*| SERCOM_I2CM_CTRLB_QCEN*/ ;
+
+
+  // Enable all interrupts
+  //I2C_SERCOM->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_ERROR ;
 
-  return true;
+  // Synchronous arithmetic baudrate
+  I2C_SERCOM->I2CM.BAUD.bit.BAUD = 48000000 / ( 2 * baudrate) - 1 ;
 }
 
-//-----------------------------------------------------------------------------
-bool i2c_write_byte(uint8_t byte)
+static inline void prepareNackBitWIRE( void )
 {
-  I2C_SERCOM->I2CM.DATA.reg = byte;
+  // Send a NACK
+  I2C_SERCOM->I2CM.CTRLB.bit.ACKACT = 1;
+}
 
-  while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB));
+static inline void prepareAckBitWIRE( void )
+{
+  // Send an ACK
+  I2C_SERCOM->I2CM.CTRLB.bit.ACKACT = 0;
+}
 
-  if (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK)
+static inline void prepareCommandBitsWire(uint8_t cmd)
+{
+  I2C_SERCOM->I2CM.CTRLB.bit.CMD = cmd;
+
+  while(I2C_SERCOM->I2CM.SYNCBUSY.bit.SYSOP)
+  {
+    // Waiting for synchronization
+  }
+}
+
+static inline bool startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag)
+{
+  // 7-bits address + 1-bits R/W
+  address = (address << 0x1ul) | flag;
+
+
+  // Wait idle or owner bus mode
+  while ( !isBusIdleWIRE() && !isBusOwnerWIRE() );
+
+  // Send start and address
+  I2C_SERCOM->I2CM.ADDR.bit.ADDR = address;
+
+  // Address Transmitted
+  if ( flag == WIRE_WRITE_FLAG ) // Write mode
+  {
+    while( !I2C_SERCOM->I2CM.INTFLAG.bit.MB )
+    {
+      // Wait transmission complete
+    }
+  }
+  else  // Read mode
+  {
+    while( !I2C_SERCOM->I2CM.INTFLAG.bit.SB )
+    {
+        // If the slave NACKS the address, the MB bit will be set.
+        // In that case, send a stop condition and return false.
+        if (I2C_SERCOM->I2CM.INTFLAG.bit.MB) {
+            I2C_SERCOM->I2CM.CTRLB.bit.CMD = 3; // Stop condition
+            return false;
+        }
+      // Wait transmission complete
+    }
+
+    // Clean the 'Slave on Bus' flag, for further usage.
+    //I2C_SERCOM->I2CM.I2CM.INTFLAG.bit.SB = 0x1ul;
+  }
+
+
+  //ACK received (0: ACK, 1: NACK)
+  if(I2C_SERCOM->I2CM.STATUS.bit.RXNACK)
   {
-    I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
     return false;
   }
+  else
+  {
+    return true;
+  }
+}
+
+static inline bool sendDataMasterWIRE(uint8_t data)
+{
+  //Send data
+  I2C_SERCOM->I2CM.DATA.bit.DATA = data;
+
+  //Wait transmission successful
+  while(!I2C_SERCOM->I2CM.INTFLAG.bit.MB) {
+
+    // If a bus error occurs, the MB bit may never be set.
+    // Check the bus error bit and bail if it's set.
+    if (I2C_SERCOM->I2CM.STATUS.bit.BUSERR) {
+      return false;
+    }
+  }
+
+  //Problems on line? nack received?
+  if(I2C_SERCOM->I2CM.STATUS.bit.RXNACK)
+    return false;
+  else
+    return true;
+}
+
+static inline void i2c_init(uint32_t baud) {
+  //Master Mode
+  initMasterWIRE(baud);
+  enableWIRE();
+
+  pin_set_peripheral_function(PINMUX_PA08C_SERCOM0_PAD0);
+  pin_set_peripheral_function(PINMUX_PA09C_SERCOM0_PAD1);
+}
 
-  return true;
+static inline void i2c_end() {
+  disableWIRE();
 }
 
-//-----------------------------------------------------------------------------
-bool i2c_busy(int addr)
+uint8_t i2c_requestFrom(uint8_t address, uint8_t quantity, bool stopBit)
 {
-  bool busy;
+  if(quantity == 0)
+  {
+    return 0;
+  }
 
-  I2C_SERCOM->I2CM.ADDR.reg = addr | I2C_TRANSFER_WRITE;
+  uint8_t byteRead = 0;
 
-  while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB));
+  rxBufferLen = 0;;
 
-  busy = (0 != (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK));
+  if(startTransmissionWIRE(address, WIRE_READ_FLAG))
+  {
+    // Read first data
+    rxBuffer[rxBufferLen++] = readDataWIRE();
+
+    // Connected to slave
+    for (byteRead = 1; byteRead < quantity; ++byteRead)
+    {
+      prepareAckBitWIRE();                          // Prepare Acknowledge
+      prepareCommandBitsWire(WIRE_MASTER_ACT_READ); // Prepare the ACK command for the slave
+      rxBuffer[rxBufferLen++] = readDataWIRE();          // Read data and send the ACK
+    }
+    prepareNackBitWIRE();                           // Prepare NACK to stop slave transmission
+    //I2C_SERCOM->I2CM.readDataWIRE();                               // Clear data register to send NACK
+
+    if (stopBit)
+    {
+      prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);   // Send Stop
+    }
+  }
 
-  I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
+  return byteRead;
+}
 
-  return busy;
+void i2c_beginTransmission(uint8_t address) {
+  // save address of target and clear buffer
+  txAddress = address;
+  txBufferLen = 0;
 }
 
-uint8_t readRegister(uint8_t startAddress) {
+// Errors:
+//  0 : Success
+//  1 : Data too long
+//  2 : NACK on transmit of address
+//  3 : NACK on transmit of data
+//  4 : Other error
+uint8_t i2c_endTransmission(bool stopBit)
+{
+
+  // Start I2C transmission
+  if ( !startTransmissionWIRE( txAddress, WIRE_WRITE_FLAG ) )
+  {
+    prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
+    return 2 ;  // Address error
+  }
+
+  // Send all buffer
+  int tempLen = txBufferLen;
+  while( txBufferLen > 0 )
+  {
+    // Trying to send data
+    if ( !sendDataMasterWIRE( txBuffer[tempLen-txBufferLen] ) )
+    {
+      prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
+      return 3 ;  // Nack or error
+    } else {
+      txBufferLen--;
+    }
+  }
+  
+  if (stopBit)
+  {
+    prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
+  }   
 
-    uint8_t DATA = 0;
-    i2c_start(PMIC_ADDRESS);
-    i2c_write_byte(startAddress);
-    i2c_stop();
+  return 0;
+}
 
-    i2c_start(PMIC_ADDRESS);
-    i2c_read_byte(&DATA, true);
-    return DATA;
+uint8_t i2c_write(uint8_t ucData)
+{
+  txBuffer[txBufferLen++] = ucData ;
+  return 1 ;
 }
 
+uint8_t readRegister(uint8_t reg) {
+  i2c_beginTransmission(PMIC_ADDRESS);
+  i2c_write(reg);
+  i2c_endTransmission(true);
+
+  i2c_requestFrom(PMIC_ADDRESS, 1, true);
+  return rxBuffer[0];
+}
 
-/*******************************************************************************
- * Function Name  :
- * Description    :
- * Input          :
- * Return         :
- *******************************************************************************/
-void writeRegister(uint8_t address, uint8_t DATA) {
+uint8_t writeRegister(uint8_t reg, uint8_t data) {
+  i2c_beginTransmission(PMIC_ADDRESS);
+  i2c_write(reg);
+  i2c_write(data);
+  i2c_endTransmission(true);
 
-    i2c_start(PMIC_ADDRESS);
-    i2c_write_byte(address);
-    i2c_write_byte(DATA);
-    i2c_stop();
+  return 2;
 }
 
 bool disableWatchdog(void) {