/*
 * TWI/I2C library for nRF5x
 * Copyright (c) 2015 Arduino LLC. All rights reserved.
 * Copyright (c) 2016 Sandeep Mistry All right reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

extern "C" {
#include <string.h>
}

#include <Arduino.h>
#include "basic.h"
#include "Wire.h"

MicroBitI2C *i2c=NULL;

TwoWire::TwoWire(uint8_t pinSDA, uint8_t pinSCL)
{
  this->_uc_pinSDA = pinSDA;
  this->_uc_pinSCL = pinSCL;
  this->transmissionBegun = false;
  this->suspended = false;
}

#ifdef ARDUINO_GENERIC
void TwoWire::setPins(uint8_t pinSDA, uint8_t pinSCL)
{
  this->_uc_pinSDA = pinSDA;
  this->_uc_pinSCL = pinSCL;
}
#endif // ARDUINO_GENERIC

void TwoWire::begin(void) {
  master = true;
  i2c = &uBit.i2c;
}

void TwoWire::setClock(uint32_t baudrate) {
  if(!i2c) return;
  i2c->frequency(baudrate);
}

void TwoWire::end() {
  *((uint32_t *)(0x40003500UL)) = (0x00UL << 0UL);   //关闭IIC，wsq
}

uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit)
{
  if (quantity == 0)
  {
    return 0;
  }
  if (quantity > SERIAL_BUFFER_SIZE)
  {
    quantity = SERIAL_BUFFER_SIZE;
  }

  size_t byteRead = 0;
  rxBuffer.clear();
  char buf[quantity];

  int erro = i2c->read(address << 1, (char*)buf, quantity, stopBit);

  if(erro == MICROBIT_I2C_ERROR)
  {
    return 0;
  }
  
  for(int i=0; i<quantity; i++){
    rxBuffer.store_char(buf[i]);
  }
  
  byteRead = quantity;

  return byteRead;
}

uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity)
{
  return requestFrom(address, quantity, false);
}

void TwoWire::beginTransmission(uint8_t address) {
  // save address of target and clear buffer
  txAddress = address;
  txBuffer.clear();

  transmissionBegun = true;
}

// Errors:
//  0 : Success
//  1 : Data too long
//  2 : NACK on transmit of address
//  3 : NACK on transmit of data
//  4 : Other error
uint8_t TwoWire::endTransmission(bool stopBit, uint32_t timeOut)
{
  transmissionBegun = false;

  int erro = i2c->write(txAddress << 1, (char*)txBuffer._aucBuffer, txBuffer._iHead == 0? 1:txBuffer._iHead,  (stopBit)? 0 : 1, timeOut);

  if(erro == MICROBIT_I2C_ERROR)
  {
      return 1;
  }

  return MICROBIT_OK;
}

uint8_t TwoWire::endTransmission()
{
  return endTransmission(true);
}

size_t TwoWire::write(uint8_t ucData)
{
  // No writing, without begun transmission or a full buffer
  if ( !transmissionBegun || txBuffer.isFull() )
  {
    return 0 ;
  }

  txBuffer.store_char( ucData ) ;

  return 1 ;
}

size_t TwoWire::write(const uint8_t *data, size_t quantity)
{
  //Try to store all data
  for(size_t i = 0; i < quantity; ++i)
  {
    //Return the number of data stored, when the buffer is full (if write return 0)
    if(!write(data[i]))
      return i;
  }

  //All data stored
  return quantity;
}

int TwoWire::available(void)
{
  return rxBuffer.available();
}

int TwoWire::read(void)
{
  return rxBuffer.read_char();
}

int TwoWire::peek(void)
{
  return rxBuffer.peek();
}

void TwoWire::flush(void)
{
  // Do nothing, use endTransmission(..) to force
  // data transfer.
  
}

TwoWire Wire(I2C_SDA0, I2C_SCL0);
