/// <summary> /// Set the target turnout /// </summary> internal void SetTarget(LocoBuffer lb) { EnterProgrammingMode(lb); SendNibble(lb, 0x01); // Command SendNibble(lb, Turnout - 1); // Turnout encoded as 0-3 }
/// <summary> /// Write the given set of SV values /// </summary> internal void Write(LocoBuffer lb, IEnumerable <SVConfig> configs) { var list = configs.ToList(); list.Sort(); foreach (var config in configs) { var ok = false; for (int attempt = 0; !ok && (attempt < ATTEMPTS); attempt++) { // Write ok = WriteSV(lb, config.Index, config.Value); // Wait a while if (!ok) { Thread.Sleep(100); } } if (!ok) { throw new ProgramException(string.Format("Failed to write SV {0}", config.Index)); } } }
/// <summary> /// Default ctor /// </summary> public LocoNet(LocoBuffer lb, LocoNetConfiguration configuration) { this.lb = lb; this.configuration = configuration; state = new LocoNetState(lb); unknownLocoIoDetector = new UnknownLocoIODetector(this); }
/// <summary> /// Set the direction of the relays. /// </summary> /// <param name="leftLsb">If true, left is the LSB and right is MSB, otherwise left is MSB and right is LSB</param> internal void SetRelaisPosition(LocoBuffer lb, bool leftLsb) { EnterProgrammingMode(lb); SendNibble(lb, 0x04); // Command SendNibble(lb, leftLsb ? 0 : 1); }
/// <summary> /// Set the right edge position in degrees /// </summary> /// <param name="value">Maximum right position (in time units) from 1 - 100</param> internal void SetRightDegrees(LocoBuffer lb, int value) { EnterProgrammingMode(lb); SendNibble(lb, 0x03); // Command SendNibble(lb, (value >> 1) & 0x07); // value bit 4,3,2 SendNibble(lb, (value >> 4) & 0x07); // value bit 7,6,5 }
/// <summary> /// Default ctor /// </summary> internal AsyncLocoBuffer(Control ui, LocoBuffer lb) { this.ui = ui; this.lb = lb; var thread = new Thread(Run); thread.Start(); }
/// <summary> /// Default ctor /// </summary> internal LocoIO(PeerXferResponse response, LocoBuffer lb) { this.lb = lb; Address = response.Source; var version = response.LocoIOVersion; Version = string.Format("{0}.{1}", version / 100, version % 100); }
/// <summary> /// Set all bits to 0. /// </summary> internal void BitsToZero(LocoBuffer lb) { if (programmingMode) { throw new InvalidOperationException("Only valid in normal mode"); } SetB4(lb, false); SetB3(lb, false); SetB2(lb, false); SetB1(lb, false); }
/// <summary> /// Execute this request. /// </summary> internal void Execute(Control ui, LocoBuffer lb) { try { request(lb); OnCompleted(ui, null); } catch (Exception ex) { OnCompleted(ui, ex); } }
/// <summary> /// Set the speed of a switch. /// </summary> /// <param name="value">Between 1 and 4</param> internal void SetSpeed(LocoBuffer lb, int value) { if ((value < 1) || (value > 4)) { throw new ArgumentException("Value must be between 1 and 4"); } EnterProgrammingMode(lb); SendNibble(lb, 0x05); // Command SendNibble(lb, SpeedMasks[value - 1] & 0x07); // LSB SendNibble(lb, (SpeedMasks[value - 1] >> 3) & 0x07); // MSB }
/// <summary> /// Set the duration from left to right /// </summary> internal void ExitProgrammingMode(LocoBuffer lb) { if (programmingMode) { SendNibble(lb, 0x07); // Command programmingMode = false; // Reset all 4 bits SetB4(lb, false); SetB3(lb, false); SetB2(lb, false); SetB1(lb, false); } }
/// <summary> /// Read the given set of SV values into configs. /// </summary> public void Read(LocoBuffer lb, IEnumerable <SVConfig> configs) { var list = configs.ToList(); list.Sort(); foreach (var iterator in configs) { var config = iterator; byte value; config.Valid = TryReadSV(lb, config.Index, out value); config.Value = value; } }
/// <summary> /// Read all settings /// </summary> internal void ReadAll(LocoBuffer lb, LocoNetAddress address) { // Create a set of all SV's that are relevant /*var configs = LocoIOConfig.GetAllSVs(); * * // Create the programmer * var programmer = new Programmer(lb, address); * * // Read all SV's * programmer.Read(configs); * * // Get all properly read configs * var validConfigs = configs.Where(x => x.Valid).ToArray(); */ }
/// <summary> /// Write a single SV variable at the given index with the given value. /// </summary> internal bool WriteSV(LocoBuffer lb, int index, byte value) { var cmd = new PeerXferRequest1 { Command = PeerXferRequest.Commands.Write, SvAddress = index, DestinationLow = address.Address, SubAddress = address.SubAddress, Data1 = value, }; var result = cmd.ExecuteAndWaitForResponse <PeerXferResponse>( lb, x => (address.Equals(x.Source) && (x.SvAddress == index) && (x.OriginalCommand == PeerXferRequest.Commands.Write)), timeout); return((result != null) && (result.Data1 == value)); }
/// <summary> /// Default ctor /// </summary> public Master(LocoBuffer lb, RailwayState railwayState, ICommandStationState cs, IStateDispatcher stateDispatcher, Logger log) { if (lb == null) { throw new ArgumentNullException("lb"); } if (cs == null) { throw new ArgumentNullException("cs"); } if (stateDispatcher == null) { throw new ArgumentNullException("stateDispatcher"); } this.railwayState = railwayState; this.lb = lb; this.log = log; this.stateDispatcher = stateDispatcher; this.cs = cs; slotTable = new SlotTable(cs); }
/// <summary> /// Default ctor /// </summary> public Client(LocoBuffer lb, RailwayState railwayState, ICommandStationState cs, IStateDispatcher stateDispatcher, Logger log) { if (lb == null) { throw new ArgumentNullException("lb"); } if (cs == null) { throw new ArgumentNullException("cs"); } if (stateDispatcher == null) { throw new ArgumentNullException("stateDispatcher"); } this.railwayState = railwayState; this.lb = lb; this.log = log; this.stateDispatcher = stateDispatcher; this.cs = cs; StartIdleDetection(); }
/// <summary> /// Write a single SV variable at the given index with the given value. /// </summary> internal bool ChangeAddress(LocoBuffer lb, int address, int subAddress) { var cmd = new PeerXferRequest1 { Command = PeerXferRequest.Commands.Write, SvAddress = 1, DestinationLow = this.address.Address, SubAddress = this.address.SubAddress, Data1 = (byte)address, }; var result = cmd.ExecuteAndWaitForResponse <PeerXferResponse>( lb, x => ((x.SvAddress == 1) && (x.OriginalCommand == PeerXferRequest.Commands.Write)), timeout); if (result == null) { throw new TimeoutException("Program index 1 failed"); } cmd = new PeerXferRequest1 { Command = PeerXferRequest.Commands.Write, SvAddress = 2, DestinationLow = this.address.Address, SubAddress = this.address.SubAddress, Data1 = (byte)subAddress, }; result = cmd.ExecuteAndWaitForResponse <PeerXferResponse>( lb, x => ((x.SvAddress == 2) && (x.OriginalCommand == PeerXferRequest.Commands.Write)), timeout); if (result == null) { throw new TimeoutException("Program index 2 failed"); } return(true); }
/// <summary> /// Go into programming mode. /// </summary> internal void EnterProgrammingMode(LocoBuffer lb) { if (!programmingMode) { // Turn all bits off SetB4(lb, false); SetB3(lb, false); SetB2(lb, false); SetB1(lb, false); Thread.Sleep(1000); // Turn bit 1 on SetB1(lb, true); Thread.Sleep(6); // Turn bit 2 on SetB2(lb, true); Thread.Sleep(6); // Turn bit 3 on SetB3(lb, true); Thread.Sleep(6); // Turn bit 4 on SetB4(lb, true); Thread.Sleep(6); // Turn bit 1 off SetB1(lb, false); Thread.Sleep(6); // Turn bit 2 off SetB2(lb, false); Thread.Sleep(6); // Turn bit 3 off SetB3(lb, false); Thread.Sleep(6); // Turn bit 4 off SetB4(lb, false); Thread.Sleep(6); programmingMode = true; } }
/// <summary> /// Read a single SV variable at the given index. /// </summary> internal bool TryReadSV(LocoBuffer lb, int index, out byte value) { var cmd = new PeerXferRequest1 { Command = PeerXferRequest.Commands.Read, SvAddress = index, DestinationLow = address.Address, SubAddress = address.SubAddress, }; var result = cmd.ExecuteAndWaitForResponse <PeerXferResponse>( lb, x => (address.Equals(x.Source) && (x.SvAddress == index) && (x.OriginalCommand == PeerXferRequest.Commands.Read)), timeout); if (result != null) { value = result.Data1; return(true); } value = 0; return(false); }
/// <summary> /// Pass the given locobuffer on to all components. /// </summary> internal void Setup(LocoBuffer lb, LocoNetConfiguration configuration) { // Allow for null arguments lb = lb ?? ConfiguredLocoBuffer; configuration = configuration ?? Configuration; if ((ConfiguredLocoBuffer != lb) || (Configuration != configuration)) { CloseLocoBuffer(); locoNet = new LocoNet(lb, configuration); asyncLb = new AsyncLocoBuffer(ui, lb); lb.SendMessage += LbForwardSendMessage; lb.PreviewMessage += LbForwardPreviewMessage; var lnState = locoNet.State; lnState.StateChanged += LnStateStateChanged; lnState.LocoIOQuery += LnStateLocoIoQuery; lnState.LocoIOFound += LnStateLocoIoFound; lnState.Idle += LnStateIdle; LocoNetChanged.Fire(this); } }
/// <summary> /// Change the type of locobuffer. /// </summary> private void OnChangeLocoBufferType(object sender, EventArgs e) { if (rbSerialPort.Checked) { if (!(LocoBuffer is SerialPortLocoBuffer)) { LocoBuffer = new SerialPortLocoBuffer(); } } else if (rbTcp.Checked) { if (!(LocoBuffer is TcpLocoBuffer)) { LocoBuffer = new TcpLocoBuffer(); } } else if (rbUdp.Checked) { if (!(LocoBuffer is UdpLocoBuffer)) { LocoBuffer = new UdpLocoBuffer(); } } }
/// <summary> /// Send a 3-bits nibble. /// </summary> private void SendNibble(LocoBuffer lb, int value) { // Lower b4 first SetB4(lb, false); // Set b1 SetB1(lb, (value & 0x01) != 0); // Set b2 SetB2(lb, (value & 0x02) != 0); // Set b3 SetB3(lb, (value & 0x04) != 0); // Raise B4 to transmit SetB4(lb, true); // Wait a while Thread.Sleep(20); // Lower B4 to avoid duplication SetB4(lb, false); // Wait a while Thread.Sleep(5); }
public override void Execute(LocoBuffer lb) { lb.Send(this, 0x83, 0); }
private void SetB4(LocoBuffer lb, bool on) { Execute(lb, new SwitchRequest { Address = Address4, Direction = on, Output = true }); }
/// <summary> /// Execute the given request. /// </summary> private static void Execute(LocoBuffer lb, Request request) { request.Execute(lb); }
/// <summary> /// Execute the message on the given buffer /// </summary> public override void Execute(LocoBuffer lb) { lb.Send(this, CreateMessage()); }
/// <summary> /// Default ctor /// </summary> /// <param name="lb"></param> internal LocoNetState(LocoBuffer lb) { this.lb = lb; lb.PreviewMessage += ProcessMessage; StartIdleDetection(); }