using System;
using System.Runtime.CompilerServices;
using System.Threading;
using Microsoft.SPOT.Hardware;
namespace HWModules
{
//TODO P2 need to lock all the I2C operations
public class I2CPortBase
{
private bool _isDiposed;
public I2CDevice.Configuration Config;
protected static I2CDevice G400I2C;
private static int _instanceCount;
private MotherBoard _mb;
private static FlPorts _flPorts;
public int SlotNumber { get; protected set; }
public I2CPortBase(I2CDevice.Configuration config, int slotnumber)
{
if (config == null)
throw new ArgumentNullException("Argument Null Exception in I2CPortBase Constructor");
this.Config = config;
if (G400I2C == null) {
G400I2C = new I2CDevice(config);
}
SlotNumber = slotnumber;
_mb = MotherBoard.Instance;
_instanceCount++;
_flPorts |= (FlPorts) (0x01 << slotnumber);
EnablePort();
Thread.Sleep(1);
}
public I2CDevice.I2CReadTransaction CreateReadTransaction(byte[] buffer)
{
if (this._isDiposed)
throw new ObjectDisposedException("Object Disposed Exception in I2CPortBase CreateReadTransaction");
return I2CDevice.CreateReadTransaction(buffer);
}
public I2CDevice.I2CWriteTransaction CreateWriteTransaction(byte[] buffer)
{
if (this._isDiposed)
throw new ObjectDisposedException("Object Disposed Exception in I2CPortBase CreateWriteTransaction");
return I2CDevice.CreateWriteTransaction(buffer);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
[MethodImpl(MethodImplOptions.Synchronized)]
private void Dispose(bool fDisposing)
{
if (!this._isDiposed) {
try {
if (_instanceCount <= 0) return;
_instanceCount--;
if (_instanceCount != 0) return;
if (G400I2C == null) return;
G400I2C.Dispose();
G400I2C = null;
}
finally {
this._isDiposed = true;
}
}
}
private static object _executelock = new object();
[MethodImpl(MethodImplOptions.Synchronized)]
public int Execute(I2CDevice.I2CTransaction[] xActions, int timeout)
{
try
{
if (this._isDiposed)
throw new ObjectDisposedException("Object Disposed Exception in I2CPortBase Execute");
int retcode = -1;
lock (_executelock) {
G400I2C.Config = this.Config;
//IsolatePort();
retcode = G400I2C.Execute(xActions, timeout);
//UnisolatePort();
}
return retcode;
}
catch
{
EngrLogger.writeToColumns("[ERROR] in I2CPortBase.Execute");
return (-1);
}
}
private void EnablePort()
{
_mb.EnableI2CPort(SlotNumber);
}
private void DisablePort()
{
_mb.DisableI2CPort(SlotNumber);
}
///
/// Isolates the i2c communication to slots
/// by disable all other buffers that have
/// been enabled before.
///
public void IsolatePort()
{
ChangeOtherPorts(false);
}
///
/// Re-enables all of the other ports that
/// have been available in the past.
///
public void UnisolatePort()
{
ChangeOtherPorts(true);
}
///
/// Changes the state of the i2c port enabling buffer to
/// disable or re-enable ports to isolate the one used here.
///
///
private void ChangeOtherPorts(bool enable)
{
//if (Config.Address != (0xCE >> 1) &&
// Config.Address != (0xD2 >> 1) &&
// Config.Address != (0xD8 >> 1))
//{
// return;
//}
FlPorts mask;
for (int i = 1; i <= 6; i++)
{
mask = (_flPorts) & ((FlPorts)(0x01 << i));
if (mask == 0 || SlotNumber == i)
continue;
if (enable)
_mb.EnableI2CPort(i);
else
_mb.DisableI2CPort(i);
Thread.Sleep(20); //allows hardware to catch up
}
}
~I2CPortBase()
{
this.Dispose(false);
}
[Flags]
private enum FlPorts
{
En0 = 0x01, //Port 0
En1 = 0x02, //Port 1
En2 = 0x04, //Port 2
En3 = 0x08, //Port 3
En4 = 0x10, //Port 4
En5 = 0x20, //Port 5
En6 = 0x40, //Port 6
}
}
}