/*******************************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
* 
* This software is protected by copyright laws of the United States and
* of foreign countries. This material may also be protected by patent laws
* and technology transfer regulations of the United States and of foreign
* countries. This software is furnished under a license agreement and/or a
* nondisclosure agreement and may only be used or reproduced in accordance
* with the terms of those agreements. Dissemination of this information to
* any party or parties not specified in the license agreement and/or
* nondisclosure agreement is expressly prohibited.
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*******************************************************************************
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RPCSupport.Devices
{
    public class I2cDevice : ClientDevice
    {
        int i2cSpeed = 1; // default to 400kHz
        const string CLASSNAME = "I2c";
        public I2cDevice(RPCClient client)
            : base(client)
        {
        }
        public void SetI2cSpeed(int speed)
        {
            i2cSpeed = speed;
        }
        public byte ReadReg(byte instance, byte slaveAddress, byte addr)
        {
            byte[] dataToWrite = new byte[] { addr };
            byte numberToRead = 1;
            byte[] data = WriteRead(instance, slaveAddress, dataToWrite, numberToRead);
            return data[0];
            //string reply1 = Call(CLASSNAME, "Init", instance.ToString("X2"), i2cSpeed.ToString("X2"));
            //string reply2 = Call(CLASSNAME, "Write", slaveAddress.ToString("X2"), "01", addr.ToString("X2"));
            //string reply3 = Call(CLASSNAME, "Read", slaveAddress.ToString("X2"), "01");
            //return client.pipeline.StringToByte(reply3);
        }
        public void WriteReg(byte instance, byte slaveAddress, byte addr, byte data)
        {
            byte[] dataToWrite = new byte[] { addr, data };
            byte numberToRead = 0;
            WriteRead(instance, slaveAddress, dataToWrite, numberToRead);
            //Call(CLASSNAME, "WriteReg", instance.ToString("X2"), slaveAddress.ToString("X2"), addr.ToString("X2"), data.ToString("X2"));
        }
        public byte[] ReadMultiReg(byte instance, byte slaveAddress, byte addr, byte numBytes)
        {
            byte[] dataToWrite = new byte[] { addr };
            byte numberToRead = (byte)numBytes;
            byte[] data = WriteRead(instance, slaveAddress, dataToWrite, numberToRead);
            return data;
            //string reply = Call(CLASSNAME, "ReadMultiReg", instance.ToString("X2"), slaveAddress.ToString("X2"), addr.ToString("X2"), numBytes.ToString("X2"));
            //return client.pipeline.StringToMultiBytes(reply, numBytes);
        }

        public void WriteMultiReg(byte instance, byte slaveAddress, byte addr, byte numberOf, byte[] data)
        {
            List<byte> dataToWrite = new List<byte>();
            dataToWrite.Add(addr);
            dataToWrite.AddRange(data);
            WriteRead(instance, slaveAddress, dataToWrite.ToArray(), 0);
            //StringBuilder sb = new StringBuilder();
            //for (int i = 0; i < numberOf; i++)
            //{
            //    sb.Append(data[i].ToString("X2"));
            //    if (i != numberOf - 1)
            //    {
            //        sb.Append(" ");
            //    }
            //}
            //Call(CLASSNAME, "WriteMultiReg", instance.ToString("X2"), slaveAddress.ToString("X2"), addr.ToString("X2"), numberOf.ToString("X2"), sb.ToString());
        }

        public void ReadReg(DeviceSupport.DeviceDetails deviceDetails, DeviceSupport.RegisterInfo reg)
        {
            byte[] dataToWrite = new byte[] { (byte)reg.address };
            byte numberToRead = (byte)reg.numBytes;
            byte[] data = WriteRead((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, dataToWrite, numberToRead);
            for (int i = 0; i < data.Length; i++)
            {
                reg.data[i] = (int)data[i];
            }            
            //if (reg.numBytes == 1)
            //{
            //    byte data = ReadReg((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, (byte)reg.address);
            //    reg.data[0] = (int)data;
            //}
            //else
            //{
            //    byte[] data = ReadMultiReg((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, (byte)reg.address, (byte)reg.numBytes);
            //    for (int i = 0; i < data.Length; i++)
            //    {
            //        reg.data[i] = (int)data[i];
            //    }
            //}
        }

        internal void WriteReg(DeviceSupport.DeviceDetails deviceDetails, DeviceSupport.RegisterInfo reg)
        {
            byte[] dataToWrite;
            byte numberToRead = 0;

            dataToWrite = new byte[reg.numBytes + 1];
            dataToWrite[0] = (byte)reg.address;
            for (int i = 0; i < reg.numBytes; i++)
            {
                dataToWrite[i + 1] = (byte)(reg.data[i]);
            }

            WriteRead((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, dataToWrite, numberToRead);
            //if (reg.numBytes == 1)
            //{
            //    WriteReg((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, (byte)reg.address, (byte)reg.data[0]);
            //}
            //else
            //{
            //    byte[] data = new byte[reg.numBytes];
            //    for (int i = 0; i < data.Length; i++)
            //    {
            //        data[i] = (byte)reg.data[i];
            //    }
            //    WriteMultiReg((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, (byte)reg.address, (byte)reg.numBytes, data);
            //}
        }

        public byte[] WriteRead(byte instance, byte slaveAddress, byte[] dataToWrite, byte numberToRead)
        {
            string dataToWriteStr = "";
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < dataToWrite.Length; i++)
            {
                sb.Append(dataToWrite[i].ToString("X2") + " ");
            }
            dataToWriteStr = sb.ToString().Trim();
            string reply = Call(CLASSNAME, "WriteRead", instance.ToString("X2"), slaveAddress.ToString("X2"), dataToWrite.Length.ToString("X2"),dataToWriteStr,  numberToRead.ToString("X2"));
            return client.pipeline.StringToMultiBytes(reply, numberToRead);
        }
    }
}
