using System.Threading;
using GHI.Pins;
using Microsoft.SPOT.Hardware;
namespace HWModules
{
public sealed class MotherBoard
{
private static OutputPort DebugLED = new OutputPort(GHI.Pins.G400S.Gpio.PC21, false);
private static OutputPort MVOpenCommandBit = new OutputPort(GHI.Pins.G400S.Gpio.PD5, false);
private static InputPort MVOpenedStatusBit = new InputPort(GHI.Pins.G400S.Gpio.PD3, true, Port.ResistorMode.Disabled);
private static InputPort MVReadyStatusBit = new InputPort(GHI.Pins.G400S.Gpio.PA3, true, Port.ResistorMode.Disabled);
private static OutputPort I2C_ENA1;
private static OutputPort I2C_ENA2;
private static OutputPort I2C_ENA3;
private static OutputPort I2C_ENA4;
private static OutputPort I2C_ENA5;
private static OutputPort I2C_ENA6;
private static OutputPort V12_RUN;
private static OutputPort V5_RUN;
private static InterruptPort CH01_NFLT;
private static InterruptPort CH02_NFLT;
private static InterruptPort CH03_NFLT;
private static InterruptPort CH04_NFLT;
private static InterruptPort CH05_NFLT;
private static InterruptPort CH06_NFLT;
private static InterruptPort CH07_NFLT;
private static InterruptPort CH08_NFLT;
private static InterruptPort CH09_NFLT;
private static InterruptPort CH10_NFLT;
private static InterruptPort CH11_NFLT;
private static InterruptPort CH12_NFLT;
private static InterruptPort CH13_NFLT;
//This is Eric's original mapping, Brent's digital board needs PA26 to be a regular GPIO
// and GM made CH14:PD2/NFLT14 (pin C6 on the backplane connector enable J4 to the
// position transducer ADC on Brent's digital board
//private static InterruptPort CH14_NFLT;
//private static InterruptPort CH15_NFLT;
private static InterruptPort CH07_NIRQ;
private static InterruptPort CH08_NIRQ;
private static InterruptPort CH09_NIRQ;
private static InterruptPort CH10_NIRQ;
private static InterruptPort CH11_NIRQ;
private static InterruptPort CH12_NIRQ;
private static InterruptPort LDR0_BUTTON;
private static InterruptPort LDR1_BUTTON;
private static OutputPort PUMP_ENA;
private static InterruptPort PUMP_FLT;
private static InputPort SD_DETECT;
//Properties
public bool Ldr0Pushed { get; set; }
public bool Ldr1Pushed { get; set; }
// create the singleton reference
private static MotherBoard _instance;
public static MotherBoard Instance
{
get
{
if (_instance == null)
_instance = new MotherBoard();
return _instance;
}
}
// Initialize all pins and configurations.
private MotherBoard()
{
//DebugLED = new OutputPort(GHI.Pins.G400S.Gpio.PC21, false);
InitI2CEnableLines();
InitSlotOutputs();
InitSlotFaults();
InitIRQLines();
InitButtons();
V12_RUN = new OutputPort(GHI.Pins.G400S.Gpio.PC18, false);
V5_RUN = new OutputPort(GHI.Pins.G400S.Gpio.PB17, false);
SD_DETECT = new InputPort(GHI.Pins.G400S.Gpio.PD7, false, Port.ResistorMode.PullUp);
InitPumpIO();
}
public enum ChannelNames
{
CTDChannel = 1,
PumpMotorControllerElexChannel,
BluetoothChannel = 3,
IridiumChannel,
FLBBChannel = 5,
OptodeChannel = 6,
MSCChannel = 7,
RadiometerChannel = 8,
phNitrateChannel,
PTHSensorChannel = 13,
PositionSensorChannel = 14,
GPSChannel = 15,
}
private static OutputPort CH01_PWR;
private static OutputPort CH02_PWR;
private static OutputPort CH03_PWR;
private static OutputPort CH04_PWR;
private static OutputPort CH05_PWR;
private static OutputPort CH06_PWR;
private static OutputPort CH07_PWR;
private static OutputPort CH08_PWR;
private static OutputPort CH09_PWR;
private static OutputPort CH10_PWR;
private static OutputPort CH11_PWR;
private static OutputPort CH12_PWR;
private static OutputPort CH13_PWR;
private static OutputPort CH14_PWR;
private static OutputPort CH15_PWR;
private static void InitSlotOutputs()
{
CH01_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PC27, false);
CH02_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PC4, false);
CH03_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PB9, false);
CH04_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PC26, false);
CH05_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PC13, false);
CH06_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PC3, false);
CH07_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PC0, false);
CH08_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PB10, false);
CH09_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PB5, false);
CH10_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PB6, false);
CH11_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PB18, false);
CH12_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PC1, false);
//This is Eric's original mapping, Brent's digital board needs PA26 to be a regular GPIO
//CH13_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PD0, false);
//CH14_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PC22, false);
//CH15_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PA29, false);
CH13_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PA29, false);
CH14_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PD2, false);
CH15_PWR = new OutputPort(GHI.Pins.G400S.Gpio.PA26, false);
}
public void EnableChannelPower(int channelnum)
{
turnChannelPowerOnOff(channelnum, true);
}
public void EnableChannelPower(ChannelNames channel)
{
turnChannelPowerOnOff((int) channel, true);
}
public void DisableChannelPower(int channelnum)
{
turnChannelPowerOnOff(channelnum, false);
}
public void DisableChannelPower(ChannelNames channel)
{
turnChannelPowerOnOff((int) channel, false);
}
public void turnChannelPowerOnOff(int channel, bool state)
{
switch (channel)
{
case 1: CH01_PWR.Write(state); break;
case 2: CH02_PWR.Write(state); break;
case 3: CH03_PWR.Write(state); break;
case 4: CH04_PWR.Write(state); break;
case 5: CH05_PWR.Write(state); break;
case 6: CH06_PWR.Write(state); break;
case 7: CH07_PWR.Write(state); break;
case 8: CH08_PWR.Write(state); break;
case 9: CH09_PWR.Write(state); break;
case 10: CH10_PWR.Write(state); break;
case 11: CH11_PWR.Write(state); break;
case 12: CH12_PWR.Write(state); break;
case 13: CH13_PWR.Write(state); break;
case 14: CH14_PWR.Write(state); break;
case 15: CH15_PWR.Write(state); break;
}
}
public bool QueryChannelPower(int channel)
{
switch (channel)
{
case 1: return CH01_PWR.Read();
case 2: return CH02_PWR.Read();
case 3: return CH03_PWR.Read();
case 4: return CH04_PWR.Read();
case 5: return CH05_PWR.Read();
case 6: return CH06_PWR.Read();
case 7: return CH07_PWR.Read();
case 8: return CH08_PWR.Read();
case 9: return CH09_PWR.Read();
case 10: return CH10_PWR.Read();
case 11: return CH11_PWR.Read();
case 12: return CH12_PWR.Read();
case 13: return CH13_PWR.Read();
case 14: return CH14_PWR.Read();
case 15: return CH15_PWR.Read();
}
return false;
}
public bool QueryChannelPower(ChannelNames channel)
{
return QueryChannelPower((int) channel);
}
private void InitIRQLines()
{
CH07_NIRQ = new InterruptPort(GHI.Pins.G400S.Gpio.PB7, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow);
CH08_NIRQ = new InterruptPort(GHI.Pins.G400S.Gpio.PC12, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow);
CH09_NIRQ = new InterruptPort(GHI.Pins.G400S.Gpio.PC11, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow);
CH10_NIRQ = new InterruptPort(GHI.Pins.G400S.Gpio.PB0, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow);
CH11_NIRQ = new InterruptPort(GHI.Pins.G400S.Gpio.PC10, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow);
CH12_NIRQ = new InterruptPort(GHI.Pins.G400S.Gpio.PB1, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow);
CH07_NIRQ.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); });
CH08_NIRQ.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); });
CH09_NIRQ.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); });
CH10_NIRQ.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); });
CH11_NIRQ.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); });
CH12_NIRQ.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); });
}
private void InitButtons()
{
LDR0_BUTTON = new InterruptPort(G400S.Gpio.PA24, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
LDR1_BUTTON = new InterruptPort(G400S.Gpio.PA4, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
LDR0_BUTTON.OnInterrupt += new NativeEventHandler((x,y,z) => {
ToggleDebugLED();
EngrLogger.Comment("LDR0 Button Pushed");
Thread.Sleep(1000); //Debounce
LDR0_BUTTON.ClearInterrupt();
Ldr0Pushed = true;
});
LDR1_BUTTON.OnInterrupt += new NativeEventHandler((x,y,z) => {
ToggleDebugLED();
EngrLogger.Comment("LDR1 Button Pushed");
Thread.Sleep(1000); //Debounce
LDR1_BUTTON.ClearInterrupt();
Ldr1Pushed = true;
});
}
private static void InitPumpIO()
{
PUMP_ENA = new OutputPort(GHI.Pins.G400S.Gpio.PC19, false);
PUMP_FLT = new InterruptPort(GHI.Pins.G400S.Gpio.PC20, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
PUMP_FLT.OnInterrupt += new NativeEventHandler((x, y, z) => { EngrLogger.Comment("Pump Unit Faulted"); PUMP_FLT.ClearInterrupt(); });
}
private static void InitI2CEnableLines()
{
I2C_ENA1 = new OutputPort(GHI.Pins.G400S.Gpio.PB11, false);
I2C_ENA2 = new OutputPort(GHI.Pins.G400S.Gpio.PB12, false);
I2C_ENA3 = new OutputPort(GHI.Pins.G400S.Gpio.PB13, false);
I2C_ENA4 = new OutputPort(GHI.Pins.G400S.Gpio.PB14, false);
I2C_ENA5 = new OutputPort(GHI.Pins.G400S.Gpio.PB15, false);
I2C_ENA6 = new OutputPort(GHI.Pins.G400S.Gpio.PB16, false);
}
private void InitSlotFaults()
{
CH01_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PC14, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
CH02_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PB4, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
CH03_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PC30, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
CH04_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PC31, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLevelLow);
CH05_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PC15, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
CH06_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PC6, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
CH07_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PB2, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
CH08_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PC24, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
CH09_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PC2, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
CH10_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PC7, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
CH11_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PB8, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
CH12_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PB3, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
CH13_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PD4, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
//This is Eric's original mapping, Brent's digital board needs PA26 to be a regular GPIO
//CH14_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PD2, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
//CH15_NFLT = new InterruptPort(GHI.Pins.G400S.Gpio.PA26, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);
//TODO P2 Remore Clear Interrupt, this should be a registered error with the faultmonitor
CH01_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 01 FAULTED"); CH01_NFLT.ClearInterrupt(); DisableChannelPower(1);});
CH02_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 02 FAULTED"); CH02_NFLT.ClearInterrupt(); DisableChannelPower(2);});
CH03_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 03 FAULTED"); CH03_NFLT.ClearInterrupt(); DisableChannelPower(3);});
CH04_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 04 FAULTED"); CH04_NFLT.ClearInterrupt(); DisableChannelPower(4);
Thread.Sleep(100); EnableChannelPower(4);
});
CH05_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 05 FAULTED"); CH05_NFLT.ClearInterrupt(); DisableChannelPower(5);});
CH06_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 06 FAULTED"); CH06_NFLT.ClearInterrupt(); DisableChannelPower(6);});
CH07_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 07 FAULTED"); CH07_NFLT.ClearInterrupt(); DisableChannelPower(7);});
CH08_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 08 FAULTED"); CH08_NFLT.ClearInterrupt(); DisableChannelPower(8);});
CH09_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 09 FAULTED"); CH09_NFLT.ClearInterrupt(); DisableChannelPower(9);});
CH10_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 10 FAULTED"); CH10_NFLT.ClearInterrupt(); DisableChannelPower(10);});
CH11_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 11 FAULTED"); CH11_NFLT.ClearInterrupt(); DisableChannelPower(11);});
CH12_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 12 FAULTED"); CH12_NFLT.ClearInterrupt(); DisableChannelPower(12);});
CH13_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 13 FAULTED"); CH13_NFLT.ClearInterrupt(); DisableChannelPower(13);});
//This is Eric's original mapping, Brent's digital board needs PA26 to be a regular GPIO
//CH14_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); EngrLogger.Comment("CHANNEL 14 FAULTED"); CH14_NFLT.ClearInterrupt(); DisableChannelPower(14);});
//CH15_NFLT.OnInterrupt += new NativeEventHandler((x, y, z) => { ToggleDebugLED(); //Debug.Print("CHANNEL 15 FAULTED"); CH15_NFLT.ClearInterrupt(); });
}
public bool SDDetected
{
get { return !(SD_DETECT.Read()); }
}
private int ct;
public void DitherDebugLED()
{
for (ct = 0; ct < 10; ct++)
ToggleDebugLED();
}
public void ToggleDebugLED()
{
DebugLED.Write(!DebugLED.Read());
}
public void EnableI2CPort(int portnum)
{
I2CPORT(portnum, true);
}
public void DisableI2CPort(int portnum)
{
I2CPORT(portnum, false);
}
private void I2CPORT(int portnum, bool state)
{
switch (portnum)
{
case 1:
I2C_ENA1.Write(state);
break;
case 2:
I2C_ENA2.Write(state);
break;
case 3:
I2C_ENA3.Write(state);
break;
case 4:
I2C_ENA4.Write(state);
break;
case 5:
I2C_ENA5.Write(state);
break;
case 6:
I2C_ENA6.Write(state);
break;
}
}
public void Enable12V()
{
V12_RUN.Write(true);
}
public void Disable12V()
{
V12_RUN.Write(false);
}
public void Enable5V()
{
V5_RUN.Write(true);
}
public void Disable5V()
{
V5_RUN.Write(false);
}
public void EnablePump()
{
PUMP_ENA.Write(true);
}
public void DisablePump()
{
PUMP_ENA.Write(false);
}
///
/// Register a delegate to take action when Interrupt Ports
/// get triggered.
///
/// Interrupt port reference
/// Delegate to be called,
/// and it must clear the IRQ as well, through a call to ClearIRQ()
public void RegisterInterruptHandler(MbInterrupt id, NativeEventHandler handler)
{
switch (id)
{
case MbInterrupt.CH07IRQ:
CH07_NIRQ.OnInterrupt += handler;
break;
case MbInterrupt.CH08IRQ:
CH08_NIRQ.OnInterrupt += handler;
break;
case MbInterrupt.CH09IRQ:
CH09_NIRQ.OnInterrupt += handler;
break;
case MbInterrupt.CH10IRQ:
CH10_NIRQ.OnInterrupt += handler;
break;
case MbInterrupt.CH11IRQ:
CH11_NIRQ.OnInterrupt += handler;
break;
case MbInterrupt.CH12IRQ:
CH12_NIRQ.OnInterrupt += handler;
break;
}
}
///
/// Clears IRQ on the related interrupt
///
///
public void ClearInterrupt(MbInterrupt id)
{
switch (id)
{
case MbInterrupt.CH07IRQ:
CH07_NIRQ.ClearInterrupt();
break;
case MbInterrupt.CH08IRQ:
CH08_NIRQ.ClearInterrupt();
break;
case MbInterrupt.CH09IRQ:
CH09_NIRQ.ClearInterrupt();
break;
case MbInterrupt.CH10IRQ:
CH10_NIRQ.ClearInterrupt();
break;
case MbInterrupt.CH11IRQ:
CH11_NIRQ.ClearInterrupt();
break;
case MbInterrupt.CH12IRQ:
CH12_NIRQ.ClearInterrupt();
break;
}
}
public void openMV()
{
MVOpenCommandBit.Write(false);
}
public void closeMV()
{
MVOpenCommandBit.Write(true);
}
public bool getMVOpenedStatus()
{
return MVOpenedStatusBit.Read(); //MVOpenedStatusBit is active low: false = open
}
public bool getMVReadyStatus()
{
return MVReadyStatusBit.Read(); //MVReadyStatusBit is active low: false = ready
}
}
public enum MbInterrupt
{
CH07IRQ,
CH08IRQ,
CH09IRQ,
CH10IRQ,
CH11IRQ,
CH12IRQ,
}
}