Breadcrumbs


Subscribe RSS


In my computer science blog I will try to provide source code snippets and small solutions, to small problems that occur often and take unexpected long time to solve :P

I am publishing these solutions in order to equalize somehow the huge amount of computer science shared knowledge, that helped me to become a better programmer :)

To all other "ambush" style "scientists" I would like to take the quote as a personal greeting:

"The secret to creativity is knowing how to hide your sources"

So I'll let those people prove themselves "creative" and will share stuff I didn't found that much online :)

Here you go a class for Serial Communication with Texas Instruments eZ430-TMS37157 RFID written on C#. I had some lot of troubles by creating this class mainly due to the lack of documentation from TI side. Nevertheless, I found a lot of sources online that I've combined and wrote some stuff by myself so I hope this code will help you too! :)

Note that the code might be a little bit inconsistent in terms of variable naming and also the communication protocol is only partially implemented, because I've needed only the message part.

 





//
// Serial Class with all stuff for communication with eZ430-TMS37157 written on C# // // by svilen.info :) // using System; using System.Collections.Generic; using System.Diagnostics; using System.IO.Ports; using System.Linq; using System.Management; using System.Runtime.Remoting.Metadata.W3cXsd2001; namespace tudos { /// <summary> /// The Type of the Serial Error /// </summary> enum SerialErrorType { OK, SEND_TIMEOUT, SEND_INVALID_OPERATION, READ_OVERLOAD, READ_TIMEOUT, NO_ANSWER } /// <summary> /// Whole Serial Message used to determine errors when class is deployed /// </summary> class SerialMessage { public string message = "OK :)"; public SerialErrorType type = SerialErrorType.OK; public object exceptionObject = null; } /// <summary> /// Serial class to deal with eZ430-TMS37157 /// </summary> class Serial { /// <summary> /// No Answer Standard /// </summary> const string NOANSWER = "010B00000000000000000000000B"; /// <summary> /// Serial Port instance /// </summary> private static SerialPort _serialPort; /// <summary> /// Last Serial Message /// </summary> public SerialMessage LastMessage { get; private set; } /// <summary> /// All received Buffers stored when debugging /// </summary> public List<byte[]> ReceivedBuffers { get; private set; } /// <summary> /// All sent buffers stored when debugging /// </summary> public List<byte[]> SentBuffers { get; private set; } /// <summary> /// Save the available comports to enable switching /// </summary> public List<COMPortInfo> AvailableComports { get; private set; } /// <summary> /// Standard Constructor to connect to eZ430-TMS37157 /// </summary> public Serial() { OpenSerial(RefreshAvailablePorts()); #if DEBUG { ReceivedBuffers = new List<byte[]>(); SentBuffers = new List<byte[]>(); } #endif LastMessage = new SerialMessage { message = "Serial Class Initialized" + DateTime.Now }; } ~Serial() { _serialPort.Close(); } /// <summary> /// Open serial port /// </summary> /// <param name="name">the unfriendly name</param> private void OpenSerial(string name) { // taking the standard settnigs of eZ430-TMS37157 _serialPort = new SerialPort { PortName = name, BaudRate = 9600, Parity = Parity.None, DataBits = 8, StopBits = StopBits.One, Handshake = Handshake.None, ReadTimeout = 500, WriteTimeout = 500 }; _serialPort.Open(); _serialPort.ErrorReceived += ErrorEvent; } /// <summary> /// Refreshes the serial ports /// </summary> /// <returns>gives back the probable unfriendly comport name of some eZ430-TMS37157</returns> private string RefreshAvailablePorts() { string portName = String.Empty; AvailableComports = COMPortInfo.GetCOMPortsInfo(); foreach (COMPortInfo comPort in AvailableComports) { Debug.WriteLine(string.Format("{0} – {1}", comPort.Name, comPort.Description)); // query the friendly name if (comPort.Description.Contains("USB Serial Port")) { portName = comPort.Name; } } return portName; } /// <summary> /// Catching the errors out of the Serial Class /// </summary> /// The Serial Class is pretty strange, as the functions don't return success parameter /// <param name="sender">Serial Class</param> /// <param name="e">System.IO.Ports.SerialError</param> private void ErrorEvent(object sender, EventArgs e) { SerialError errorOccured = ((SerialErrorReceivedEventArgs)e).EventType; switch (errorOccured) { case SerialError.TXFull: break; case SerialError.RXOver: break; case SerialError.Overrun: break; case SerialError.RXParity: break; case SerialError.Frame: break; default: throw new ArgumentOutOfRangeException(); } } /// <summary> /// Read One Buffer /// </summary> /// <param name="receivedBuffer"></param> /// <returns></returns> public SerialMessage ReadBuffer(out byte[] receivedBuffer) { try { if (!_serialPort.IsOpen) { _serialPort.Open(); } string buffer = _serialPort.ReadTo("\r\n "); buffer = _serialPort.ReadTo("\r\n"); if ("" != _serialPort.ReadExisting()) { receivedBuffer = null; return new SerialMessage { message = "Serial Receive Overload", type = SerialErrorType.READ_OVERLOAD }; } if (buffer == NOANSWER) { receivedBuffer = null; return new SerialMessage { message = "Serial Received No Answer", type = SerialErrorType.NO_ANSWER }; } byte[] framedBuffer = BufferConverter.GetStringToBytes(buffer); receivedBuffer = RemoveFrames(framedBuffer); #if DEBUG { ReceivedBuffers.Add(receivedBuffer); } #endif return new SerialMessage(); } catch (TimeoutException e) { receivedBuffer = null; return new SerialMessage { message = "Serial", exceptionObject = e, type = SerialErrorType.READ_TIMEOUT }; } } /// <summary> /// Writes buffer to the comport /// </summary> /// <param name="buffer">buffer to write</param> /// <returns>success status</returns> public SerialMessage WriteBuffer(byte[] buffer) { try { if (!_serialPort.IsOpen) { _serialPort.Open(); } byte[] fullBuffer = AddFrames(buffer); _serialPort.Write(BufferConverter.GetBytesToString(fullBuffer)); #if DEBUG { SentBuffers.Add(fullBuffer); } #endif //_serialPort.Close(); } catch(TimeoutException e) { LastMessage = new SerialMessage { message = "Command Send Time Out: " + e.Message, type = SerialErrorType.SEND_TIMEOUT, exceptionObject = e }; return LastMessage; } catch (InvalidOperationException e) { LastMessage = new SerialMessage { message = "Command Send Invalid Operation: " + e.Message, type = SerialErrorType.SEND_INVALID_OPERATION, exceptionObject = e }; return LastMessage; } LastMessage = new SerialMessage { message = "Command Sent", }; return LastMessage; } /// <summary> /// Add the headers to the raw buffer /// </summary> /// <param name="rawBuffer">buffer body</param> /// <returns>framed buffer</returns> byte[] AddFrames(byte[] rawBuffer) { const int HEADERS_LENGHT = 6; const int FOOTERS_LENGHT = 5; const int FRAMES_LENGTH = HEADERS_LENGHT + FOOTERS_LENGHT; byte[] buffer = new byte[rawBuffer.Length + FRAMES_LENGTH]; buffer[0] = 0x01; // fixed buffer[1] = (byte)(rawBuffer.Length + FRAMES_LENGTH - 3); // size of buffer buffer[2] = 0x06; // CMD1 buffer[3] = 0x32; // PB1 buffer[4] = 0x48; // #TX Bits buffer[5] = 0x7d; // MSP ACCESS Write Address Array.Copy(rawBuffer, 0, buffer, 6, rawBuffer.Length); // Actual Data byte[] CRCData = buffer.Skip(5).Take(7).ToArray(); // Data for the CRC byte[] CRC = Crc16Ccitt.GetCRC(CRCData); // The Actual CRC buffer[HEADERS_LENGHT + rawBuffer.Length] = CRC[0]; // CRC MSB buffer[HEADERS_LENGHT + rawBuffer.Length + 1] = CRC[1]; // CRC LSB buffer[HEADERS_LENGHT + rawBuffer.Length + 2] = 0x0F; // PB2 buffer[HEADERS_LENGHT + rawBuffer.Length + 3] = 0x0A; // Size of awaited Answer (add this to variable some day to check...) byte[] LRCData = buffer.Skip(1).Take(buffer.Length - 2).ToArray(); byte lrc = LRC.calculateLRC(LRCData); buffer[buffer.Length - 1] = lrc; // LRC return buffer; } /// <summary> /// Remove frames from the buffer /// </summary> /// <param name="rawBuffer">framed buffer</param> /// <returns>body buffer</returns> byte[] RemoveFrames(byte[] rawBuffer) { const int HEADERS_LENGHT = 6; const int BODY_LENGTH = 6; byte[] CRCData = rawBuffer.Skip(5).Take(7).ToArray(); // Data for the CRC byte[] CRC = Crc16Ccitt.GetCRC(CRCData); // The Actual CRC if (CRC[0] != rawBuffer[HEADERS_LENGHT + BODY_LENGTH] && CRC[1] != rawBuffer[HEADERS_LENGHT + BODY_LENGTH + 1]) { // throw CRC error } byte[] LRCData = rawBuffer.Skip(1).Take(rawBuffer.Length - 2).ToArray(); byte lrc = LRC.calculateLRC(LRCData); if (rawBuffer[rawBuffer.Length - 1] != lrc) { // throw LRC error } return rawBuffer.Skip(4).Take(6).ToArray(); } } /// <summary> /// Convert byte buffers back and forth /// </summary> static class BufferConverter { static public byte[] GetStringToBytes(string value) { SoapHexBinary shb = SoapHexBinary.Parse(value); return shb.Value; } static public string GetBytesToString(byte[] value) { SoapHexBinary shb = new SoapHexBinary(value); return shb.ToString(); } } /// <summary> /// Cyclic Redundancy Check (CRC) /// </summary> /// CCITT (x^16 + x^12 + x^5 + 1) public static class Crc16Ccitt { public static byte[] GetCRC(byte[] data) { ushort crc = 0x3791; // eZ430-TMS37157 initial value for (byte i = 0; i < data.Length; i++) { byte bits = 8; byte current = data[i]; // Next byte while (bits-- > 0) { bool lsb = (crc & 1) > 0; // Store LSB crc >>= 1; // Shift right 1 bit bool rxdt = (current & 1) > 0; if (rxdt) { crc |= 0x8000; // Shift in next bit } if (lsb) // Check stored LSB { crc ^= 0x8000; // Invert MSB } if (0x8000 == (crc & 0x8000)) // Check MSB { crc ^= 0x0408; // Invert bits 3 and 10 (have in mind those are x^12 and x^5) } current >>= 1; // Next bit } } return BitConverter.GetBytes(crc); } } /// <summary> /// Longitudinal Redundancy Check (LRC) /// </summary> public static class LRC { public static byte calculateLRC(byte[] bytes) { byte LRC = 0; for (int i = 0; i < bytes.Length; i++) { LRC ^= bytes[i]; } return LRC; } } /// <summary> /// Get Friendly Comport Names :) /// </summary> /// based on http://dariosantarelli.wordpress.com/2010/10/18/c-how-to-programmatically-find-a-com-port-by-friendly-name/ public class COMPortInfo { public string Name; public string Description; public static List<COMPortInfo> GetCOMPortsInfo() { List<COMPortInfo> comPortInfoList = new List<COMPortInfo>(); ManagementScope connectionScope = new ManagementScope { Path = new ManagementPath(@"\\" + Environment.MachineName + @"\root\CIMV2"), Options = new ConnectionOptions { Impersonation = ImpersonationLevel.Impersonate, Authentication = AuthenticationLevel.Default, EnablePrivileges = true } }; connectionScope.Connect(); ObjectQuery objectQuery = new ObjectQuery("SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0"); ManagementObjectSearcher comPortSearcher = new ManagementObjectSearcher(connectionScope, objectQuery); using (comPortSearcher) { string caption; foreach (ManagementObject obj in comPortSearcher.Get()) { if (obj != null) { object captionObj = obj["Caption"]; if (captionObj != null) { caption = captionObj.ToString(); if (caption.Contains("(COM")) { COMPortInfo comPortInfo = new COMPortInfo { Name = caption.Substring(caption.LastIndexOf("(COM")).Replace("(", string.Empty).Replace(")", string.Empty), Description = caption }; comPortInfoList.Add(comPortInfo); } } } } } return comPortInfoList; } } }

It's time for new blog post, briefly about how to deal with implementing easy bit field structure layout in C :)

Let us see the following structure in C++

 

10 /*****************************************************************************

11 *

12 *    Splitt structure we are about to cast :)

13 *

14 *****************************************************************************/

15

16 // prototype C++

17

18 const int A_Flag_width = 2;

19 const int A_FrameID_width = 6;

20 const int A_Link_width = 8;

21 const int A_SplittID_width = 8;

22 const int A_Empty_width = 8;

23

24 typedef struct

25 {

26 DWORD32 A_Flag : A_Flag_width;

27 DWORD32 A_FrameID : A_FrameID_width;

28 DWORD32 A_Link: A_Link_width;

29 DWORD32 A_SplittID : A_SplittID_width;

30 DWORD32 A_Empty: A_Empty_width;

31 DWORD32 B_CRC;

32 char * Data;

33 }

34 splitt_struct;

35

36 /****************************************************************************/

It represents a recent structure I wanted to code in C about some Frame with header, which should be splitted in structure called Splitt, that has also some header and look like above declared. So to spare space you might wanna have precise bit layout. One way to deal nicely with bitlayouts are the bitfields like this (click), other way is to use bitsets (click), also few others using diverse libraries.

Anyway, enough said, the C variant is this:

 

39 /*****************************************************************************

40 *

41 *    This is the nice C variant :)

42 *

43 *****************************************************************************/

44

45 // define shit C

46

47 typedef char structure;

48 typedef structure * p_structure;

49

50

51 #define MEMBER_POINTER(number,t)                (t *)((p_structure)Example + number * sizeof(t))

52 #define MEMBER_VALUE(number,t)                    (*MEMBER_POINTER(number, t))

53

54 #define SUBMEMBER_CLEAR(member, t, start, end)    do { MEMBER_VALUE(member, t) &= ~(((SIZE_MAX << end) >> (end + start)) << start); } while (0);

55 #define SUBMEMBER_GET(member, t, start, end)    ((MEMBER_VALUE(member, t) << end) >> (end + start))

56 #define SUBMEMBER_SET(member, t, val, start, end) do { SUBMEMBER_CLEAR(member, t, start, end); MEMBER_VALUE(member, t) |= val << start ; } while (0);

57

58 #define MEMBER_LAST_BIT(t)                        (8 * sizeof(t) - 1)

59 #define END_OFFSET(t, end)                        (MEMBER_LAST_BIT(t) - end)

60

61

62 typedef structure Splitt;

63 typedef p_structure p_Splitt;

64

65 #define splitt Example

66

67 #define A                                        0

68 #define CRC                                        1

69 #define DATA                                    2

70

71 #define A_flag_start                            0

72 #define A_flag_end                                END_OFFSET(size_t, 1)

73 #define A_FID_start                                2

74 #define A_FID_end                                END_OFFSET(size_t, 7)

75 #define A_Link_start                            8

76 #define A_Link_end                                END_OFFSET(size_t, 15)

77 #define A_SID_start                                16

78 #define A_SID_end                                END_OFFSET(size_t, 23)

79 #define A_Empty_start                            24

80 #define A_Empty_end                                END_OFFSET(size_t, 31)

81

82 #define splitt_flag_get                            (SUBMEMBER_GET(A, DWORD32, A_flag_start, A_flag_end))

83 #define splitt_flag_set(val)                    SUBMEMBER_SET(A, DWORD32, val, A_flag_start, A_flag_end)

84 #define splitt_FID_get                            (SUBMEMBER_GET(A, DWORD32, A_FID_start, A_FID_end))

85 #define splitt_FID_set(val)                        SUBMEMBER_SET(A, DWORD32, val, A_FID_start, A_FID_end)

86 #define splitt_link_get                            (SUBMEMBER_GET(A, DWORD32, A_Link_start, A_Link_end))

87 #define splitt_link_set(val)                    SUBMEMBER_SET(A, DWORD32, val, A_Link_start, A_Link_end)

88 #define splitt_SID_get                            (SUBMEMBER_GET(A, DWORD32, A_SID_start, A_SID_end))

89 #define splitt_SID_set(val)                        SUBMEMBER_SET(A, DWORD32, val, A_SID_start, A_SID_end)

90 #define splitt_empty_get                        (SUBMEMBER_GET(A, DWORD32, A_Empty_start, A_Empty_end))

91 #define splitt_empty_set(val)                    SUBMEMBER_SET(A, DWORD32, val, A_Empty_start, A_Empty_end)

92

93 #define p_splitt_CRC                            (MEMBER_POINTER(CRC, DWORD32))

94 #define splitt_CRC                                (*p_splitt_CRC)

95

96 #define splitt_data                                MEMBER_POINTER(DATA, p_Splitt)

97

98

99 /****************************************************************************/

Nice :)

To explain briefly, I cast all to byte buffer and then use some shifting functions to extract different bit fields! (taking mask for example is pretty easy by shifting the other bits left and right to clear them). The code shown also forces using the name splitt for Splitt (e.g. you cannot use the functions after declaring "Splitt bubble")(I find this good).

What you can further do is to have the nice defines in "template style" way and then cast a multiple structures with the token pasting operator, which will make your code to look like the real deal! (I did it but then reduced the structures so it turned out to be obsolete)

You can also nest common headers with defines, which I also did with the structures later on (not shown, too much stuff)

Anyway, I don't intend to explain any further for now, just click to download the code with example test!

Heyo this is a small example, how to Marshall c structures to c# for the usb chip. The example shows a static c# class :)

(Download .cs)

1 ///

2 /// author svilen.info / svilen.de

3 ///

4 /// no copyright, however please cite source XD

5 ///

6 /// some small example, how the c -> c# marshalling works here!

7 ///

8

9 using System;

10 using System.Diagnostics;

11 using System.Runtime.InteropServices;

12 using System.Text;

13

14 namespace Zarlink.Adk.Forms

15 {

16 /// <summary>

17 /// This class will deal with the USB communication

18 /// </summary>

19 /// Here we will cast all the ftd2xx.h functions and structure that we need

20 /// and will add some other specific communaction protocols

21 static class Communication

22 {

23 #region My Variables

24

25 public static FT_STATUS status;     // represents the FT status. To be updated after every action!

26

27 public static IntPtr handle;         // represents the FT device handle. Should be always the same, if varies then something is wrong (like more usbs)

28

29

30 public struct Buffer

31 {

32 public byte[] data;                 // data from the last successful transfer

33 public DateTime lastSuccessfulUse;  // if connection lost, to check the date and time of the last successful data transfer

34 }

35

36 public static Buffer inBuffer;      // what we received last

37 public static Buffer outBuffer;     // what we sent last

38

39 #endregion My Variables

40

41 #region Stupid defines from the dll

42

43 // FT_OpenEx Flags

44 private const UInt16 FT_OPEN_BY_SERIAL_NUMBER = 1;

45 private const UInt16 FT_OPEN_BY_DESCRIPTION = 2;

46 private const UInt16 FT_OPEN_BY_LOCATION = 4;

47

48 // Baud Rates

49 private const UInt32 FT_BAUD_300 = 300;

50 private const UInt32 FT_BAUD_600 = 600;

51 private const UInt32 FT_BAUD_1200 = 1200;

52 private const UInt32 FT_BAUD_2400 = 2400;

53 private const UInt32 FT_BAUD_4800 = 4800;

54 private const UInt32 FT_BAUD_9600 = 9600;

55 private const UInt32 FT_BAUD_14400 = 14400;

56 private const UInt32 FT_BAUD_19200 = 19200;

57 private const UInt32 FT_BAUD_38400 = 38400;

58 private const UInt32 FT_BAUD_57600 = 57600;

59 private const UInt32 FT_BAUD_115200 = 115200;

60 private const UInt32 FT_BAUD_230400 = 230400;

61 private const UInt32 FT_BAUD_460800 = 460800;

62 private const UInt32 FT_BAUD_921600 = 921600;

63

64 // Word Lengths

65 private const byte FT_BITS_8 = 8;

66 private const byte FT_BITS_7 = 7;

67 private const byte FT_BITS_6 = 6;

68 private const byte FT_BITS_5 = 5;

69

70

71 // Stop Bits

72 private const byte FT_STOP_BITS_1 = 0;

73 private const byte FT_STOP_BITS_1_5 = 1;

74 private const byte FT_STOP_BITS_2 = 2;

75

76 // Parity

77 private const byte FT_PARITY_NONE = 0;

78 private const byte FT_PARITY_ODD = 1;

79 private const byte FT_PARITY_EVEN = 2;

80 private const byte FT_PARITY_MARK = 3;

81 private const byte FT_PARITY_SPACE = 4;

82

83 // Flow Control

84 private const UInt16 FT_FLOW_NONE = 0x0000;

85 private const UInt16 FT_FLOW_RTS_CTS = 0x0100;

86 private const UInt16 FT_FLOW_DTR_DSR = 0x0200;

87 private const UInt16 FT_FLOW_XON_XOFF = 0x0400;

88

89 // Purge rx and tx buffers

90 public const byte FT_PURGE_RX = 1;

91 public const byte FT_PURGE_TX = 2;

92

93 // Events

94 public const byte FT_EVENT_RXCHAR = 1;

95 public const byte FT_EVENT_MODEM_STATUS = 2;

96 public const byte FT_EVENT_LINE_STATUS = 4;

97

98 // Timeouts

99 private const UInt32 FT_DEFAULT_RX_TIMEOUT = 300;

100 private const UInt32 FT_DEFAULT_TX_TIMEOUT = 300;

101

102 #endregion Stupid defines

103

104 #region Stupid Marshals

105

106 /// <summary>

107 /// marshalling the structure...

108 /// </summary>

109 [StructLayout(LayoutKind.Sequential)]

110 public struct LPFTDCB

111 {

112 public UInt32 DCBlength;      /* sizeof(FTDCB)                   */

113 public UInt32 BaudRate;       /* Baudrate at which running       */

114

115 public UInt32 fBits;            // bits layout is inportable so have the flag and take out the bits

116 //ulong fBinary: 1;     /* Binary Mode (skip EOF check)    */

117 //ulong fParity: 1;     /* Enable parity checking          */

118 //ulong fOutxCtsFlow:1; /* CTS handshaking on output       */

119 //ulong fOutxDsrFlow:1; /* DSR handshaking on output       */

120 //ulong fDtrControl:2;  /* DTR Flow control                */

121 //ulong fDsrSensitivity:1; /* DSR Sensitivity              */

122 //ulong fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */

123 //ulong fOutX: 1;       /* Enable output X-ON/X-OFF        */

124 //ulong fInX: 1;        /* Enable input X-ON/X-OFF         */

125 //ulong fErrorChar: 1;  /* Enable Err Replacement          */

126 //ulong fNull: 1;       /* Enable Null stripping           */

127 //ulong fRtsControl:2;  /* Rts Flow control                */

128 //ulong fAbortOnError:1; /* Abort all reads and writes on Error */

129 //ulong fDummy2:17;     /* Reserved                        */

130

131 public UInt16 wReserved;       /* Not currently used              */

132 public UInt16 XonLim;          /* Transmit X-ON threshold         */

133 public UInt16 XoffLim;         /* Transmit X-OFF threshold        */

134

135 public byte ByteSize;        /* Number of bits/byte, 4-8        */

136 public byte Parity;          /* 0-4=None,Odd,Even,Mark,Space    */

137 public byte StopBits;        /* 0,1,2 = 1, 1.5, 2               */

138

139 public char XonChar;         /* Tx and Rx X-ON character        */

140 public char XoffChar;        /* Tx and Rx X-OFF character       */

141 public char ErrorChar;       /* Error replacement char          */

142 public char EofChar;         /* End of Input character          */

143 public char EvtChar;         /* Received Event character        */

144

145 public ushort wReserved1;    /* Fill for now.                   */

146 } ;

147

148 #endregion Stupid Marshals

149

150 #region Constructors, Destructors ...

151

152 static Communication()

153 {

154 handle = IntPtr.Zero;

155

156 outBuffer = new Buffer { data = new byte[140], lastSuccessfulUse = DateTime.Now };

157 inBuffer = new Buffer { data = new byte[140], lastSuccessfulUse = DateTime.Now };

158 }

159

160 //static ~Communication()

161 //{

162 //    Close();

163 //}

164

165 #endregion Constructors, Destructors ...

166

167 #region W32 Functions from the dll

168 // note: W32 should not be mixed with non W32 unless explicitly stated

169

170

171 /// <summary>

172 /// This function gets the current device state.

173 /// </summary>

174 /// <param name="ftHandle">Cast PVOID to IntPtr to have system specific handle pointer size</param>

175 /// <param name="lpftDcb">the status</param>

176 /// <returns>If the function is successful, the return value is nonzero</returns>

177 [DllImport("ftd2xx")]

178 public static extern bool FT_W32_GetCommState(IntPtr ftHandle, ref LPFTDCB lpftDcb);

179

180 #endregion W32 Functions

181

182 #region Normal Functions that we use from the dll

183

184 [DllImport("ftd2xx")]

185 public static extern FT_STATUS FT_ResetDevice(IntPtr ftHandle);

186

187 [DllImport("ftd2xx")]

188 public static extern FT_STATUS FT_ClrDtr(IntPtr ftHandle);

189

190 [DllImport("ftd2xx")]

191 public static extern FT_STATUS FT_ClrRts(IntPtr ftHandle);

192

193 [DllImport("ftd2xx")]

194 public static extern FT_STATUS FT_Open(UInt32 uiPort, IntPtr ftHandle);

195

196 [DllImport("ftd2xx")]

197 public static extern FT_STATUS FT_Close(IntPtr ftHandle);

198

199 [DllImport("ftd2xx")]

200 public static extern FT_STATUS FT_Read(IntPtr ftHandle, out byte[] lpBuffer, UInt32 dwBytesToRead, out UInt32 lpdwBytesReturned);

201

202 [DllImport("ftd2xx")]

203 public static extern FT_STATUS FT_Write(IntPtr ftHandle, IntPtr lpBuffer, UInt32 dwBytesToRead, ref UInt32 lpdwBytesWritten);

204

205 [DllImport("ftd2xx")]

206 public static extern FT_STATUS FT_SetLatencyTimer(IntPtr ftHandle, byte ucTimer);

207

208 [DllImport("ftd2xx")]

209 public static extern FT_STATUS FT_SetDataCharacteristics(IntPtr ftHandle, byte uWordLength, byte uStopBits, byte uParity);

210

211 [DllImport("ftd2xx")]

212 public static extern FT_STATUS FT_SetFlowControl(IntPtr ftHandle, ushort usFlowControl, byte uXon, byte uXoff);

213

214 [DllImport("ftd2xx")]

215 public static extern FT_STATUS FT_GetModemStatus(IntPtr ftHandle, ref UInt32 lpdwModemStatus);

216

217 [DllImport("ftd2xx")]

218 public static extern FT_STATUS FT_Purge(IntPtr ftHandle, UInt32 dwMask);

219

220 [DllImport("ftd2xx")]

221 public static extern FT_STATUS FT_SetBreakOn(IntPtr ftHandle);

222

223 [DllImport("ftd2xx")]

224 public static extern FT_STATUS FT_SetBreakOff(IntPtr ftHandle);

225

226 [DllImport("ftd2xx")]

227 public static extern FT_STATUS FT_GetStatus(IntPtr ftHandle, ref UInt32 lpdwAmountInRxQueue, ref UInt32 lpdwAmountInTxQueue, ref UInt32 lpdwEventStatus);

228

229 [DllImport("ftd2xx")]

230 public static extern FT_STATUS FT_SetDivisor(IntPtr ftHandle, char usDivisor);

231

232 #endregion Normal Functions

233

234 #region Functions written by Svilen ;)

235

236 public static void DebugInformation(string step = "")

237 {

238 Debug.WriteLine(step + " status: " + status);

239 Debug.WriteLine("handle address: " + handle);

240 unsafe

241 {

242 if (handle != null)

243 {

244 Debug.WriteLine("handle value: " + *(uint*) handle.ToPointer()); // to use in unsafed code

245 }

246 }

247 //Debug.WriteLine("handle value: " + *(uint *)handle.ToPointer()); // to use in unsafed code

248 }

249

250 public static void Init()

251 {

252 // > open >

253 FT_Open(0, handle);

254 DebugInformation("open");

255 // < open <

256

257 // > reset! >

258 FT_ResetDevice(handle);

259 DebugInformation("reset");

260 // < reset! <

261

262 // > set reply rate

263 FT_SetLatencyTimer(handle, 2);

264 DebugInformation("latency timer");

265 // < set reply rate <

266

267 // > set same flow control

268 FT_SetFlowControl(handle, FT_FLOW_RTS_CTS, 0, 0);

269 DebugInformation("flow control");

270 // < set flow control <

271

272

273 // > clear the buffers >

274 FT_Purge(handle, FT_PURGE_TX + FT_PURGE_RX);

275 DebugInformation("purge");

276 // < clear the buffers <

277 }

278

279 public static void ReadTest()

280 {

281 byte[] bytes = new byte[20];

282 IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);

283 Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);

284 IntPtr bytesLeft = (IntPtr)10;

285

286 // FT_Read(handle, unmanagedPointer, (UInt32)bytes.Length, bytesLeft);

287 DebugInformation("read");

288

289 Marshal.Copy(unmanagedPointer, bytes, 0, bytes.Length);

290 ASCIIEncoding enc = new ASCIIEncoding();

291 Debug.WriteLine("buffer has: " + enc.GetString(bytes));

292

293 Marshal.FreeHGlobal(unmanagedPointer);

294 }

295

296 public static int ReadBuffer()

297 {

298 UInt32 bytesLeft;

299 inBuffer.data = new byte[140];

300

301 FT_Read(handle, out inBuffer.data, (UInt32)inBuffer.data.Length, out bytesLeft);

302 DebugInformation("read");

303

304 ASCIIEncoding enc = new ASCIIEncoding();

305 if (inBuffer.data != null)

306 Debug.WriteLine("buffer has: " + enc.GetString(inBuffer.data));

307

308 return 0;

309 }

310

311 public static void WriteTest()

312 {

313 IntPtr ptr = Marshal.AllocHGlobal(4);

314 Marshal.Copy(outBuffer.data, 0, ptr, 4);

315

316 uint bytesWritten = 0;

317 FT_Write(handle, ptr, 4, ref bytesWritten);

318

319 DebugInformation("write");

320 }

321

322 public static void Close()

323 {

324 if (handle == IntPtr.Zero)

325 {

326 FT_Close(handle);

327 DebugInformation("close");

328 }

329 }

330

331 #endregion Functions

332

333 #region other defines and enumerations for the communication namespace

334

335 /// <summary>

336 /// Enumaration containing the varios return status for the DLL functions.

337 /// </summary>

338 public enum FT_STATUS

339 {

340 FT_OK = 0,

341 FT_INVALID_HANDLE,

342 FT_DEVICE_NOT_FOUND,

343 FT_DEVICE_NOT_OPENED,

344 FT_IO_ERROR,

345 FT_INSUFFICIENT_RESOURCES,

346 FT_INVALID_PARAMETER,

347 FT_INVALID_BAUD_RATE,

348 FT_DEVICE_NOT_OPENED_FOR_ERASE,

349 FT_DEVICE_NOT_OPENED_FOR_WRITE,

350 FT_FAILED_TO_WRITE_DEVICE,

351 FT_EEPROM_READ_FAILED,

352 FT_EEPROM_WRITE_FAILED,

353 FT_EEPROM_ERASE_FAILED,

354 FT_EEPROM_NOT_PRESENT,

355 FT_EEPROM_NOT_PROGRAMMED,

356 FT_INVALID_ARGS,

357 FT_OTHER_ERROR

358 }

359

360 #endregion other defines and enumerations for the communication namespace

361 }

362 }

363

Simle test of my Compute Frequency function using some code citation tool...

public int[] ComputeFrequency(byte[] samples, bool stereo, bool bit16)
{
 int stereoDiv = stereo ? 2 : 1;
 int bitDiv = bit16 ? 2 : 1;

 int sampleIterator;                  // stop iterating when second peak on each channel has been found
 int[] firstPeaks = { 0, 0 };         // the first peak positions in the sample array
 bool[] cleanPeaks = { false, false };// check whether we started the sample in the middle of some peak
 int[] returnFrequency = { 0, 0 };

 for (sampleIterator = 0; sampleIterator < SAMPLE_SIZE; sampleIterator++)
 {
 byte[] sampleData = { samples[stereoDiv * bitDiv * sampleIterator], 0 };

 if (stereo)
 {
 sampleData[SECOND_CHANNEL] = samples[stereoDiv * bitDiv * sampleIterator + bitDiv];
 }

 for (int channel = 0; channel < stereoDiv; channel++)
 {
 // works for both int and byte because we want to check out we passed the middle
 if (sampleData[channel] < 150 && sampleData[channel] > 20)
 {
 cleanPeaks[channel] = true;
 }

 if (sampleData[channel] >= PEAK_LEVEL_8 && cleanPeaks[channel])
 {
 if (firstPeaks[channel] == 0)
 {
 cleanPeaks[channel] = false;
 firstPeaks[channel] = sampleIterator;
 // make assumption about the frequency that is not lower than the sampling / 2000
 sampleIterator += SAMPLING_RATE / 2000 * stereoDiv * bitDiv;
 }
 else // we found second peak, which is at position [k]
 {
 if (returnFrequency[channel] == 0)
 {
 // pitch as the sample frequency divided by the distance between two peaks
 returnFrequency[channel] = SAMPLING_RATE / (sampleIterator - firstPeaks[channel]);
 }

 if (returnFrequency[FIRST_CHANNEL] > 0 && returnFrequency[SECOND_CHANNEL] > 0)
 {
 return returnFrequency;
 }
 }
 }
 }
 }
 return returnFrequency;
}