#ifndef _BM_IIC_H_
#define _BM_IIC_H_

#include "Wire.h"
#include "Arduino.h"

class BM_SW_IIC
{
  public:

    void begin(void);
    void beginTransmission(uint8_t addr);
    uint8_t endTransmission(uint8_t stop);
    uint8_t write(uint8_t data);
    uint8_t read(void);
    uint8_t peek(void);
    uint8_t available(void);
    uint8_t requestFrom(uint8_t addr, uint8_t len, uint8_t sendStop);
    void ChangeIICPin(uint8_t iic_sck, uint8_t iic_sda);
    void delay();
    void setClock(uint32_t clockDiv);
    
    void setWireTimeout(uint32_t timeout,uint8_t reset_with_timeout);
    bool getWireTimeoutFlag(void);
    uint8_t clearWireTimeoutFlag(void);
    void end(void);
    
  private:
    uint8_t iic_start(void);
    uint8_t iic_stop(void);
    uint8_t iic_waitack(void);
    uint8_t iic_ack(void);
    uint8_t iic_nack(void);
    uint8_t iic_write(uint8_t data);
    uint8_t iic_read(uint8_t* flag);

    uint8_t _scl;
    uint8_t _sda;
    uint8_t _rxBuf[255];
    uint8_t _txBuf[255];
    uint8_t _rxBufNum = 0;
    uint16_t _txBufNum = 0;
    uint16_t _bufReadNum;
    uint32_t _iicClock;
    uint8_t _timeEn;
    uint32_t _timeOut;
    uint32_t _time1;
    uint32_t _time2;
    uint8_t _timeFlag;
    uint8_t _begin = 0;
};

class BM_IIC
{
  public:
    BM_IIC();
    BM_IIC(uint8_t addr);
    BM_IIC(uint8_t scl,uint8_t sda);
    BM_IIC(uint8_t addr, uint8_t scl, uint8_t sda );
    void begin(void);
    void begin(uint8_t address);
    void begin(int address);
    void end(void);
    void setClock(uint32_t clockDiv);
    void setWireTimeout(uint32_t timeout,uint8_t reset_with_timeout);
    bool getWireTimeoutFlag(void);
    uint8_t clearWireTimeoutFlag(void);
    void onReceive(void (*handler)(int));
    void onRequest(void (*handler)(void));

    void beginTransmission(uint8_t addr);
    void beginTransmission(int address);

    uint8_t endTransmission();
    uint8_t endTransmission(uint8_t stop);

    uint8_t requestFrom(uint8_t addr, uint8_t quantity,uint8_t sendStop);
    uint8_t requestFrom(uint8_t addr, uint8_t quantity);
    uint8_t requestFrom(int addr, int quantity,int sendStop);
    uint8_t requestFrom(int addr, int quantity);
    uint8_t requestFrom(uint8_t addr, uint8_t quantity,uint32_t iaddress,uint8_t isize,uint8_t sendStop);

    uint8_t write(unsigned long data);
    uint8_t write(long data); 
    uint8_t write(unsigned int data);
    uint8_t write(int data);
    uint8_t write(uint8_t data);
    uint8_t read(void);
    uint8_t peek(void);
    
    uint8_t writeBytes(uint8_t *buffer, uint8_t len, uint8_t stop = 1);
    uint8_t writeByte(uint8_t data,uint8_t stop = 1);
    uint8_t readBytes(uint8_t *buffer, uint8_t len, uint8_t stop = 1);
    uint8_t readByte(uint8_t stop = 1);
    uint8_t available(void);
    uint8_t maxBufferSize(void);

    uint8_t _sda;
    uint8_t _scl;
  private:
    uint8_t _addr;
    BM_SW_IIC* _the_BM_IIC;
    TwoWire* _the_TwoWire;
    BM_SW_IIC _BM_IIC;

};
#endif
