2 using System.Collections.Generic;
18 private string _SerialNumber =
"";
26 public string SerialNumber
28 get {
return _SerialNumber; }
29 set { _SerialNumber = value; }
38 if (SerialNumber.IsNullOrWhiteSpace())
40 Log.
Exception(
"Could not initialize FT245RBitbangController {0}. SerialNumber has not been set.".Build(Name));
45 Log.
Write(
"FT245RBitbangController {0} with serial number {1} has been initialized and the updater thread has been started.".Build(Name, SerialNumber));
54 FinishUpdaterThread();
55 Log.
Write(
"FT245RBitbangController {0} with serial number {1} has been finished and the updater thread has been terminated.".Build(Name, SerialNumber));
63 if (NewValue != CurrentValue)
65 UpdaterThreadSignal();
73 private void AddOutputs()
75 for (
int i = 1; i <= 8; i++)
77 if (!Outputs.Any(x => x.Number == i))
79 Outputs.Add(
new Output() { Name =
"{0}.{1:00}".Build(Name, i), Number = i });
101 if (!ON.
Number.IsBetween(1, 64))
103 throw new Exception(
"FT245RBitbangController output numbers must be in the range of 1-8. The supplied output number {0} for FT245RBitbangController with serial number {1} is out of range.".Build(ON.
Number, SerialNumber));
108 lock (ValueChangeLocker)
110 NewValue |= (byte)(1 << (ON.
Number - 1));
115 lock (ValueChangeLocker)
117 NewValue &= (byte)~(1 << (ON.
Number - 1));
125 #region UpdaterThread
126 private void InitUpdaterThread()
133 if (!UpdaterThreadIsActive)
135 KeepUpdaterThreadAlive =
true;
138 UpdaterThread =
new Thread(UpdaterThreadDoIt);
139 UpdaterThread.Name =
"FT245RBitbangController {0} named {1} updater thread ".Build(SerialNumber, Name);
140 UpdaterThread.Start();
144 Log.
Exception(
"FT245RBitbangController {0} named {1} updater thread could not start.".Build(SerialNumber, Name), E);
145 throw new Exception(
"FT245RBitbangController {0} named {1} updater thread could not start.".Build(SerialNumber, Name), E);
154 private void FinishUpdaterThread()
156 if (UpdaterThread != null)
160 KeepUpdaterThreadAlive =
false;
161 UpdaterThreadSignal();
162 if (!UpdaterThread.Join(1000))
164 UpdaterThread.Abort();
166 UpdaterThread = null;
170 Log.Exception(
"A error occured during termination of FT245RBitbangController ({0}) updater thread.".Build(SerialNumber), E);
171 throw new Exception(
"A error occured during termination of FT245RBitbangController ({0}) updater thread.".Build(SerialNumber, E));
180 public bool UpdaterThreadIsActive
184 if (UpdaterThread != null)
186 if (UpdaterThread.IsAlive)
198 private void UpdaterThreadSignal()
200 lock (UpdaterThreadLocker)
202 Monitor.Pulse(UpdaterThreadLocker);
206 private object ValueChangeLocker =
new object();
207 private byte NewValue = 0;
208 private byte CurrentValue = 255;
211 private Thread UpdaterThread {
get; set; }
212 private object UpdaterThreadLocker =
new object();
213 private bool KeepUpdaterThreadAlive =
true;
214 private int FirstTryFailCnt = 0;
215 private void UpdaterThreadDoIt()
221 Log.
Warning(
"No connection to FTDI chip {0}. Updater thread will terminate.".Build(SerialNumber));
231 Log.Exception(
"Could not send initial update to FTDI chip {0}. Updater thread will terminate.".Build(SerialNumber));
237 while (KeepUpdaterThreadAlive)
239 lock (ValueChangeLocker)
241 CurrentValue = NewValue;
247 SendUpdate(CurrentValue);
252 if (FirstTryFailCnt < 5)
254 Log.Exception(
"Could not send update to FTDI chip {0} on first try. Will reconnect and send update again.".Build(SerialNumber), E);
256 if (FirstTryFailCnt == 5)
258 Log.Warning(
"Will not log futher warnings on first try failures when sending data to FTDI chip {0}.".Build(SerialNumber));
272 Log.Exception(
"Could not send update to FTDI chip {0}. Tried to reconnect to device but failed. Updater thread will terminate.".Build(SerialNumber), EC);
281 SendUpdate(CurrentValue);
286 Log.Exception(
"Could not send update to FTDI chip {0}. Reconnect to device worked, but sending the update did fail again. Updater thread will terminate.".Build(SerialNumber), EE);
294 Log.Exception(
"Could not send update to FTDI chip {0}. Tried to reconnect to device but failed. Updater thread will terminate.".Build(SerialNumber));
299 if (KeepUpdaterThreadAlive)
301 lock (UpdaterThreadLocker)
303 while (NewValue == CurrentValue && KeepUpdaterThreadAlive)
305 Monitor.Wait(UpdaterThreadLocker, 50);
317 Log.Exception(
"Final update to turn off all output fo FTDI chip {0} failed.".Build(SerialNumber), E);
324 #region FT245R Communication
326 object FTDILocker =
new object();
329 private void Connect()
340 if (SerialNumber.IsNullOrWhiteSpace())
342 Log.Exception(
"The SerialNumber has not been set for the FT245RBitbangController named {0}. Cant connect to device.".Build(Name));
351 FTDI.ErrorHandler(FTDI.OpenBySerialNumber(SerialNumber));
355 Log.Exception(
"Could not open the connection to FTDI chip with serial number {0}.".Build(SerialNumber), E);
363 FTDI.ErrorHandler(FTDI.SetBitMode(0xFF, FTDI.FT_BIT_MODES.FT_BIT_MODE_SYNC_BITBANG));
367 Log.Exception(
"Could set the bitmode to bitbang for FTDI chip with serial number {0}.".Build(SerialNumber), E);
373 Log.Write(
"Connection to FTDI chip {0} established.".Build(SerialNumber));
382 private void SendUpdate(byte OutputData)
389 byte[] Out = { OutputData };
392 FTDI.FT_STATUS Status = FTDI.Write(Out, 1, ref numBytes);
393 if (Status != FTDI.FT_STATUS.FT_OK)
396 FTDI.ErrorHandler(Status);
400 throw new Exception(
"Wrong number of written bytes (expected 1, received {0} was returned when sending data to the FTDI chip {1}".Build(numBytes, SerialNumber));
406 private void Disconnect()
423 FTDI.ErrorHandler(FTDI.Close());
427 Log.Exception(
"A exception occured when closing the FTDI chip {0}.".Build(SerialNumber));
431 Log.Write(
"Connection to FTDI chip {0} closed.".Build(SerialNumber));
This is a generic output controller class which are based on the FT245R chip (http://www.ftdichip.com/Products/ICs/FT245R.htm). Only units using the chip in bitbang mode are supported by this output controller class. The SainSmart USB relay boards (http://www.sainsmart.com/arduino-compatibles-1/relay/usb-relay.html) are compatible with this output controller, but other hardware which is based on the same controller chip might be compatible as well. Generally controller units which is exclusively using the FT245R (no extra cpu on board) and having max. 8 output ports are likely to be compatible. Please let me know, if you have tested other hardware successfully, so I can ammend the docu.
The Cabinet object describes the parts of a pinball cabinet (toys, outputcontrollers, outputs and more).
int Number
Gets or sets the number of the Output object.
FT245RBitbangController()
Initializes a new instance of the FT245RBitbangController class.
override void Update()
Signals the workerthread that all pending updates for the FT245RBitbangController should be sent to t...
override void Finish()
Finishes the FT245RBitbangController object. Finish does also terminate the workerthread.
byte Value
Value of the output.
static void Warning(string Message)
Writes a warning message to the log.
static void Write(string Message)
Writes the specified message to the logfile.
A simple logger used to record important events and exceptions.
Common interface for outputs of any output controller. The Output class implements this interface and...
Abstract OutputController base class to be used for IOutputController implementations. Implements IOutputController.
Common interface for all outputcontrollers. Only classes implementing this interface can be used as o...
override void OnOutputValueChanged(IOutput Output)
This method is called whenever the value of a output in the Outputs property changes its value...
override void Init(Cabinet Cabinet)
Initializes the FT245RBitbangController and starts the updater thread.
static void Exception(string Message, Exception E=null)
Writes a exception message to the log.
Basic IOutput implementation.