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, } }