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; } } } [MethodImpl(MethodImplOptions.Synchronized)] public int Execute(I2CDevice.I2CTransaction[] xActions, int timeout) { if (this._isDiposed) throw new ObjectDisposedException("Object Disposed Exception in I2CPortBase Execute"); G400I2C.Config = this.Config; //IsolatePort(); int retcode = G400I2C.Execute(xActions, timeout); //UnisolatePort(); return retcode; } 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 } } }