Main Site Documentation

Snippet - Bluetooth module bluetooth_42.cs file for 4.3


#1

I just posted Bluetooth module bluetooth_42.cs file for 4.3 on Codeshare. Feel free to discuss and make suggestions here.


#2

Hi,
are there any modifications to this?


Cheers
Roland


#3

I don’t know that gadgeteer code contains GHI modules.

Why gadgeteer code contains 4.3 code module although ghi sdk doesn’t ?
And how can I access this gadgeteer module in vs ?


#4

It seems the 4.3 versions of the module drivers are just copies of 4.2 code. Newest driver code from GHI is here: https://bitbucket.org/ghi_elect/gadgeteer/src/a15ccac69ab6/Modules/GHIElectronicsLegacy/Bluetooth/?at=master


#5

You need to download the legacy SDK from GHI https://www.ghielectronics.com/docs/299/discontinued-gadgeteer-product-drivers


#6

I know I must install Discontinued Products SDK and it is what I have done. But I contain only 4.2 version. That’s why I have upgraded this snippet with 4.3.


#7

Hi,
@ njbuch It seems that GHI already ported the Bluetooth Driver to NETMF 4.3.
As far as I see, the main difference from 4.2 to 4.3 is the code for the Serial port and the Output and Input Socket Pins.
@ Bauland Did you make additionally other modifications?
There were some issues with the GHI Bluetooth driver 4.2 in the past. So @ vbdaniel and I posted modifications of the GHI driver. I did not try the GHI driver in the last months. Does it now work without problems for you?
Cheers
Roland


#8

@ RoSchmi: No additional modifications have been made.

I’m currently rewrite @ vbdaniel one in c# for 4.3 because I’m newbie in Gadgeteer, and I didn’t know that GHI driver causes some trouble.

I am a little confused with serial port: is it to communicate with module or connected device with Bluetooth ?

Cheers


#9

Snippet deleted as asked by @ andre.m.


#10

Anyway, thanks for your efforts.
There is so much content in the NETMF / Gadgeteer area that it is impossible to know what is already done.


#11

both…
until the devices are connected you communicate with the modue.
When the connection is established all communication path trought the module to the
connected device. now you can’t communicate with the module anymore until the connection is lost

Daniel


#12

Thanks for explanation it is clear now.

But with @ RoSchmi or @ GHI module or @ VB-Daniel, what I try to do, module blocks on State 2 (in slave mode).


#13

I didn’t yet get the time to port my driver to 4.3. Which mainboard are you using?
Which changes did you make in the driver?

Edit:
Keep in mind: It only connects e.g. to a PC if you have a terminal program like teraterm on the PC side, which is listening to the selected Serial Port of the PC.

Alternatively you can use an RFComm Connection on the PC side e.g. with the 32feet.net library which is used in my PC/Bluetooth file Transfer Project in Codeshare.
(If you have a 64 bit Windows Version you must open VS as administrator to run the PC-Client on the PC side)


#14

I use Spider, I don’t have change any functionnality, just port code to 4.3, but even in 4.2, I can see device on my WP8 or my PC, but can’t connect.


#15

Pairing works with no problems?
At the moment I can not help with WP8, perhaps you try PC first


#16

what application do you have on the other side ??
I think you maybe can’t pair without an app on the otherside.
But I mostly use the host mode

  1. Computerside
    • using blootooth as com port
    • easy application opening an serial port
      then
  2. start paring on gadgeteer side

Be carefull ! Everytime you set the pincode of the module (even if it the same)
you need the whole pairing dialog on both side. If you set the pin only once the the next pairing is no pin needed.

Daniel


#17

Except that it seems to never quit State 2.

I’ll get a try with host mode on spider and client on pc …


#18

Then you must use the driver of @ vbdaniel. For my Driver I don’t know whether host mode works.


#19

Hi,
got my driver working for 4.3 and Spider. If you want, you can give it a try.
Needs some more work to post it on CodeShare

Bluetooth.cs


// This is a Gadgeteer driver for the GHI Bluetooth Module, NETMF V. 4.3
// the original driver is from Eduardo Velloso -https://gadgeteerbluetooth.codeplex.com/
// Modification to set the baudrate of the Bluetooth module were made by 
// Brett Pound -https://gadgeteerbluetooth.codeplex.com/discussions/357827
// This modification by R.o.l.a.n.d S.c.h.m.i.d.t is intended to improve the setting of the baudrate of the Bluetooth Module
// and to reach higher data rates for incoming data
// Any of the possible baudrates of the serial port of the BT-Module can now reliably (at least I hope so) be selected in the constructor.
// Don't change the baudrate with the "SetDeviceBaud" command from outside the driver (connection between mainboard and BT-Module is lost
// due to consecutive bautrate mismatch)
// additional features are that data can be sent and received additionally as Byte Arrays (only strings in the former versions)
// additionally a fastReadMode "bluetooth.SetFastReadMode(true)" is realized. This command can be used after the BT connection
// is established. It has has a significant effekt only in ReadMode_ByteArray mode. Bauderates of more then 100.000 can be reached. 
// In this mode the incoming data are not longer parsed for AT-commands and are transferred in large chunks. 
// For fast reading of data use "bluetooth.SetReadMode_ByteArray(true)" and "bluetooth.SetFastReadMode(true)"

using System;
//using System.IO.Ports;
using Microsoft.SPOT;
using System.Threading;
using System.Text;
using System.Collections;

using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using GTI = Gadgeteer.SocketInterfaces;



namespace Gadgeteer.Modules.RoSchmi
{
    /// <summary>
    /// A Bluetooth module for Microsoft .NET Gadgeteer
    /// </summary>
    public class Bluetooth : GTM.Module
    {

            /// <summary>
            /// Direct access to Serial Port.
            /// </summary>
            /// 
            // Note by RoSchmi: Reference Gadgeteer.Serial must be added
            public GTI.Serial serialPort;
            private  GTI.DigitalOutput reset;
            private GTI.InterruptInput statusInt;
            private Thread readerThread;
            
            //Added by RoSchmi
            string atCommand = "";
            int state = 0;
            int first = 0;
            int mid = 0;
            int last = 0;

            int LF_Offset = 0;
            int timeOutCtr = 0;

            // Don't change the size of RingBufferLength and ReadChunk if there is no need
            // the following combination was testes and works
            const int RingBufferLength = 2000;
            const int ReadChunk = 400;

            byte[] RingBuffer = new byte[RingBufferLength];
            int ReadPtr = 0;
            int WritePtr = 0;
            double StartTicks;
            private bool fastReadMode = false;
            private bool readerThread_isRunning = false;
            private bool ReadMode_ByteArray = false;
            private bool readerThreadAllowedToRun = false;
            private bool constructorThreadAllowedToRun = true;
            private int readerThreadLoopCounter = 0;
            private bool baudrate_found = false;
            private int eventDelay = 20;


            static public AutoResetEvent Wait_For_Baudrates_Match;

           // We take the possible baudrates two times in the array to try each baudrate two times to test for matching
            long[] possibleBaudrates = new long[16] { 0, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 
                                                      0, 9600, 19200, 38400, 57600, 115200, 230400, 460800};
            //End Added by RoSchmi

        /// <summary>
        /// Possible states of the Bluetooth module
        /// </summary>
            public enum BluetoothState
            {
                /// <summary>
                /// Module is initializing
                /// </summary>
                Initializing = 0,
                /// <summary>
                /// Module is ready
                /// </summary>
                Ready = 1,
                /// <summary>
                /// Module is in pairing mode
                /// </summary>
                Inquiring = 2,
                /// <summary>
                /// Module is making a connection attempt
                /// </summary>
                Connecting = 3,
                /// <summary>
                /// Module is connected
                /// </summary>
                Connected = 4,
                /// <summary>
                /// Module is diconnected
                /// </summary>
                Disconnected = 5
            }

            //Constructors changed by RoSchmi

            // Note: A constructor summary is auto-generated by the doc builder.
            /// <summary></summary>
            /// <param name="socketNumber">The socket that this module is plugged in to.</param>
            public Bluetooth(int socketNumber)
            {
                Complete_Common_Constructor(socketNumber, 38400);
            }

            // Note: A constructor summary is auto-generated by the doc builder.
            /// <summary></summary>
            /// <param name="socketNumber">The socket that this module is plugged in to.</param>
            /// <param name="baud">The baud rate to communicate with the module with.</param>
            public Bluetooth(int socketNumber, long baud)
            {
                
                // Throw an exception if a not allowed baudrate is passed as argument
                int pos = Array.IndexOf(possibleBaudrates, baud);
                if (!(pos >- 1)|(baud == 0))
                {
                    throw new System.ArgumentException("Argument of parameter baud (baudrate) not allowed. "
                                              + "Use 9600, 19200, 38400, 57600, 115200, 230400 or 460800");
                }
                Complete_Common_Constructor(socketNumber, baud);
            }

            private void Complete_Common_Constructor(int socketNumber, long baud)    // Common part of constructor
            {
                Thread.Sleep(1000);      // not thoroughly test

                // This finds the Socket instance from the user-specified socket number.  
                // This will generate user-friendly error messages if the socket is invalid.
                // If there is more than one socket on this module, then instead of "null" for the last parameter, 
                // put text that identifies the socket to the user (e.g. "S" if there is a socket type S)
                Socket socket = Socket.GetSocket(socketNumber, true, this, null);

                this.reset = GTI.DigitalOutputFactory.Create(socket, Socket.Pin.Six, false, this);
                this.statusInt = GTI.InterruptInputFactory.Create(socket, Socket.Pin.Three, GTI.GlitchFilterMode.Off, GTI.ResistorMode.Disabled, GTI.InterruptMode.RisingAndFallingEdge, this);
                this.serialPort = GTI.SerialFactory.Create(socket, (int) baud, GTI.SerialParity.None, GTI.SerialStopBits.One, 8, GTI.HardwareFlowControl.NotRequired, this);

                //this.statusInt.Interrupt += (statusInt_Interrupt);



                this.serialPort.ReadTimeout = Timeout.Infinite;
                this.serialPort.Open();
                Thread.Sleep(5);

                this.reset.Write(true);

               
                 Thread.Sleep(500);   // not thoroughly test

                possibleBaudrates[0] = baud;   // try first to connect with baudrate passed to the constructor as argument
                                               // if not successful with this baudrate, we try all possible baudrates two times
                possibleBaudrates[8] = baud;   // preset for the second run
                
                Wait_For_Baudrates_Match = new AutoResetEvent(false);

                // Create instance of DataByteArrayReceivedHandler
                onDataByteArrayReceived = new DataByteArrayReceivedHandler(OnDataByteArrayReceived);

                // Create instance of DataReceivedHandler
                onDataReceived = new DataReceivedHandler(OnDataReceived);

                for (int i = 0; i < possibleBaudrates.Length; i++)
                {
                     while (!constructorThreadAllowedToRun)
                     {
                         Thread.Sleep(1);  
                     }
                     constructorThreadAllowedToRun = false;
                     
                     this.serialPort.Flush();
                     this.serialPort.Close();
                     this.serialPort.BaudRate = (int)possibleBaudrates[i];
                     this.serialPort.Open();
                     Debug.Print("Message from Class Bluetooth 1: Baudrate set to " + this.serialPort.BaudRate);

                    Debug.Print("Message from Class Bluetooth: Try to set BT-Module baudrate to: " + possibleBaudrates[i].ToString());
                    this.SetDeviceBaud(possibleBaudrates[i]);  // try to set baudrate of BT-Module on this baudrate
                    Thread.Sleep(100);                                           // if we have the baudrate to which the
                                                               // BT-Module is actually set we will get
                                                               // "OK" or "ERROR" and the bautrate is set to the new
                                                               // value, otherwise we get not readable signs and the
                                                               // new bautrate will not be set
                    
                    readerThreadLoopCounter = 0;               // Synchronisation with reader Thread
                    readerThreadAllowedToRun = true;
                    
                    if (!readerThread_isRunning)  // if readerThread is not running, start new readerThread
                    {
                        readerThread = new Thread(new ThreadStart(runReaderThread));
                        readerThread.Start();
                        readerThread_isRunning = true;
                        Thread.Sleep(50);
                    }

                    constructorThreadAllowedToRun = false;        // Synchronisation with reader Thread
                    readerThreadLoopCounter = 0;
                    readerThreadAllowedToRun = true;
                    
                    StartTicks = DateTime.Now.Ticks;
                    if (Wait_For_Baudrates_Match.WaitOne(500, false)) // Wait for matching bautrates
                    {
                        Debug.Print("Message from Class Bluetooth: Could connect to BT-Module with baudrate " + possibleBaudrates[i].ToString() + " in " + ((DateTime.Now.Ticks - StartTicks) * 0.0001).ToString() + " msec");
                         while (!constructorThreadAllowedToRun)
                         {
                             Thread.Sleep(1);
                         }
                         constructorThreadAllowedToRun = false;
                         Thread.Sleep(5);
                         if (possibleBaudrates[i] != baud)
                         {
                             //Debug.Print("Message from Class Bluetooth: Set BT-Device_Baudrate to baudrate passed as argument: " + baud.ToString());
                             this.SetDeviceBaud(baud);   // Set BT-Module to baudrate passed as argument
                             this.serialPort.Flush();
                             this.serialPort.Close();
                             //Debug.Print("Message from Class Bluetooth 2: Set serialPort to baudrate passed as argument: " + baud.ToString());
                             this.serialPort.BaudRate = (int)baud;
                             Debug.Print("Message from Class Bluetooth 2: Baudrate set to " + this.serialPort.BaudRate);
                             this.serialPort.Open();
                         }
                         baudrate_found = true;
                         this.serialPort.DiscardInBuffer();
                         readerThreadLoopCounter = 0;
                         readerThreadAllowedToRun = true;
                        break;
                    }
                    else
                    {
                        Debug.Print("Message from Class Bluetooth: Could not connect to BT-Module with baudrate " + possibleBaudrates[i].ToString() + " in " + ((DateTime.Now.Ticks - StartTicks) * 0.0001).ToString() + " msec");
                    }
                }
               
            }

            /// <summary>
            /// Hard Reset Bluetooth module
            /// </summary>
            public void Reset()
            {
                this.reset.Write(false);
                Thread.Sleep(5);
                this.reset.Write(true);
            }

            /// <summary>
            /// Gets a value that indicates whether the bluetooth connection is connected.
            /// </summary>
            public bool IsConnected
            {
                get
                {
                    return this.statusInt.Read();
                }
            }
            
            //  Added by RoSchmi
            /// <summary>
            /// Sets FastReadMode: true: no parsing of serial data to increase speed, false: parsing for messages from BT-Module
            /// </summary>
            /// <param name="mode">The states of FastReadMode, true or false (</param>
            public void SetFastReadMode(bool mode)
            {
                this.fastReadMode = mode;
                Debug.Print("Set fastReadMode: " + mode);
            }

            /// <summary>
            /// Gets the state of FastReadMode: true: no parsing of serial data to increase speed, false: parsing for messages from BT-Module
            /// </summary>
            public bool GetFastReadMode()
            {
                return this.fastReadMode;
            }
            /// <summary>
            /// Sets ReadMode_ByteArray: true: ReadData come as ByteArray, false: ReadData come as string
            /// </summary>
            /// <param name="byteArrayMode">The states of ReadMode_ByteArray, true or false (</param>
            public void SetReadMode_ByteArray(bool byteArrayMode)
            {
                this.ReadMode_ByteArray = byteArrayMode;
            }
            /// <summary>
            /// Gets ReadMode_ByteArray: true: ReadData come as ByteArray, false: ReadData come as string
            /// </summary>
            public bool GetReadMode_ByteArray()
            {
                return this.ReadMode_ByteArray;
            }
            /// <summary>
            /// Sets or gets a timedelay, if events queue up, set a higher value than 20 ms
            /// </summary>
            /// <param name="enventDelay">Timedelay - does not work ByteArrayMode combined with fastReadMod (</param>
            public int EventDelay
            {
                get { return eventDelay; }
                set { eventDelay = value; }
            }
         
        // Reader Thread changed by RoSchmi

        /// <summary>
        /// Thread that continuously reads incoming messages from the module,
        /// parses them and triggers the corresponding events.
        /// </summary>
            private void runReaderThread()
            {
                byte[] SendBuffer = new byte[2000];
                byte[] SendBuffer_2 = new byte[2000];
                //byte[] SendBuffer;
                int SendBufferPtr = 0;
                int SendTimeOut = 0;

                byte[] ReadBuffer = new byte[ReadChunk + 1];
                int bytesToSend = -1;
                int BytesRead = 0;
                int i2 = 0;
                int ActBytes = 0;              // Used for calculations
                int BufLenAdd = 0;             // Used for calculations
                int RestCountInBuffer = 0;     // Used for calculations
                String response = "";
                
                while (true)
                {
                       // Reset fastReadMode when connection is lost
                       if (this.IsConnected == false)             
                       {
                           if (this.fastReadMode)
                           {
                               Debug.Print("Set fastReadMode: false");
                           }
                           this.fastReadMode = false;
                       }

                       // Test if there is free space for a new chunk in Ringbuffer, if not do not read a new chunk from serialPort

                       BufLenAdd = 0;
                       if (WritePtr >= ReadPtr)
                       {
                           BufLenAdd = RingBuffer.Length;
                       }
                       if (((BufLenAdd - WritePtr) + ReadPtr) > ReadChunk)  // enough space for new ReadChunk

                       {
                           if (!baudrate_found)
                           {
                               while (!readerThreadAllowedToRun)     //Synchronization with thread in constructor
                               {
                                   Thread.Sleep(1);
                               }
                               readerThreadLoopCounter++;
                               if (readerThreadLoopCounter > 10)         // We can read 10 chunks of data to get
                               {                                         // a message from the BT-module to see
                                   readerThreadAllowedToRun = false;     // if we have a working baudrate
                                   constructorThreadAllowedToRun = true;
                                   readerThreadLoopCounter = 0;
                               }
                           }

                           BytesRead = 0;
                           if (this.serialPort.BytesToRead > 0)
                           {
                               BytesRead = this.serialPort.Read(ReadBuffer, 0, ReadChunk);
                           }
                           
                           // Write new data chunk in RingBuffer
                           if (WritePtr == RingBuffer.Length)
                           {
                               WritePtr = 0;
                           }
                           if ((WritePtr + BytesRead) < RingBuffer.Length)
                           {
                               Array.Copy(ReadBuffer, 0, RingBuffer, WritePtr, BytesRead);
                               WritePtr += BytesRead;
                           }
                           else
                           {
                               Array.Copy(ReadBuffer, 0, RingBuffer, WritePtr, RingBuffer.Length - WritePtr);
                               Array.Copy(ReadBuffer, (RingBuffer.Length - WritePtr),RingBuffer,0, BytesRead - (RingBuffer.Length - WritePtr));
                               WritePtr = BytesRead - (RingBuffer.Length - WritePtr);
                           }
                       }
                       
                       
                       if (ReadMode_ByteArray && fastReadMode)   // if true, we directly send the data without parsing
                       {
                           BufLenAdd = 0;
                           if (WritePtr >= ReadPtr)
                           {
                               BufLenAdd = RingBuffer.Length;
                           }
                           
                           RestCountInBuffer = (RingBuffer.Length - BufLenAdd) + WritePtr - ReadPtr;

                           if (WritePtr >= ReadPtr)
                           {
                               RestCountInBuffer = WritePtr - ReadPtr;
                           }
                           else
                           {
                               RestCountInBuffer =  RingBuffer.Length - ReadPtr + WritePtr;
                           }
                               
                               if (SendBufferPtr + RestCountInBuffer < SendBuffer.Length)
                               {
                                   if ((ReadPtr + RestCountInBuffer) <= RingBuffer.Length)
                                   {
                                       Array.Copy(RingBuffer, ReadPtr, SendBuffer, SendBufferPtr, RestCountInBuffer);
                                       SendBufferPtr += RestCountInBuffer;
                                   }
                                   else
                                   {
                                       Array.Copy(RingBuffer, ReadPtr, SendBuffer, SendBufferPtr, RingBuffer.Length - ReadPtr);
                                       SendBufferPtr += (RingBuffer.Length - ReadPtr);
                                       Array.Copy(RingBuffer, 0, SendBuffer, SendBufferPtr, RestCountInBuffer - (RingBuffer.Length - ReadPtr));
                                       SendBufferPtr += (RestCountInBuffer - (RingBuffer.Length - ReadPtr));
                                   }
                                   if (SendTimeOut > 100)
                                   {
                                       //Debug.Print("SendTimeOut > 100: " + SendBufferPtr.ToString());

                                       Array.Copy(SendBuffer, SendBuffer_2, SendBufferPtr);
                                       OnDataByteArrayReceived(this, SendBuffer_2, 0, SendBufferPtr);
                                       SendBufferPtr = 0;
                                       SendTimeOut = 0;
                                   }
                                   ReadPtr = WritePtr;    //Buffer is now empty
                               }
                               else
                               {
                                   //Debug.Print("Sendbuffer full:" + SendBufferPtr.ToString());
                                   Array.Copy(SendBuffer, SendBuffer_2, SendBufferPtr);
                                   OnDataByteArrayReceived(this, SendBuffer_2, 0, SendBufferPtr);
                                   SendBufferPtr = 0;
                                   SendTimeOut = 0;
                               }

                            SendTimeOut++;
                       }
                       else   // Not (ReadMode_ByteArray && FastReadMode) 
                       {
                           // gets bytes to send from ringbuffer to next linefeed
                           // if there are more than (readchunk * 2) bytes in ringbuffer
                           // or if we have tried mor then 50 times to read from the
                           // ringbuffer we get the remaining contents of the ringbuffer

                           bytesToSend = this.sendDisplacement() + 1;  

                           response = "";
                           if ((ReadPtr + bytesToSend) <= RingBuffer.Length)
                           {
                               //response = new String(Encoding.UTF8.GetChars(RingBuffer, ReadPtr, bytesToSend));
                               
                               for (i2 = 0; i2 < bytesToSend; i2++)
                               {
                                    response = response + (char)RingBuffer[ReadPtr + i2];
                               }
                               

                           }
                           else
                           {
                               //response = new String(Encoding.UTF8.GetChars(RingBuffer, ReadPtr, (RingBuffer.Length - ReadPtr)));
                               //response += new String(Encoding.UTF8.GetChars(RingBuffer, 0, (bytesToSend - (RingBuffer.Length - ReadPtr))));
                               
                               ActBytes = RingBuffer.Length - ReadPtr;
                               for (i2 = 0; i2 < ActBytes; i2++)
                               {
                                   response = response + (char)RingBuffer[ReadPtr + i2];
                               }
                               ActBytes = bytesToSend - (RingBuffer.Length - ReadPtr);
                               for (i2 = 0; i2 < (ActBytes); i2++)
                               {
                                   response = response + (char)RingBuffer[i2];
                               }
                                
                           }

                            if ((response != null) && (response.Length > 0))
                            {
                                if (!ReadMode_ByteArray && fastReadMode)   // if fastreadMode == true, we send without parsing
                                {
                                    OnDataReceived(this, response);
                                    
                                    if ((ReadPtr + (bytesToSend - 1)) >= RingBuffer.Length)
                                    {
                                        ReadPtr = ((bytesToSend - 1) - (RingBuffer.Length - ReadPtr)) + 1;
                                    }
                                    else
                                    {
                                        ReadPtr = ReadPtr + bytesToSend;
                                    }
                                }
                                else
                                {
                                //Check Bluetooth State Changed
                                atCommand = "+BTSTATE:";
                                first = response.IndexOf(atCommand);
                                if (first > -1)
                                {
                                    // If the text "+BTSTATE:" is received the first time, we see that
                                    if (!baudrate_found)  // we have a working baudrate and we release AutoResetEvent
                                    {                     // Wait_For_Baudrates_Match.WaitOne
                                        Wait_For_Baudrates_Match.Set();
                                    }

                                    //String parsing  
                                    // Return format: +COPS:<mode>[,<format>,<oper>]
                                    state = -1;
                                    first += atCommand.Length;
                                    if (response.Length >= first)
                                    {
                                        switch (response[first])
                                        {
                                            case (Char)0x30:
                                                state = 0;
                                                break;
                                            case (Char)0x31:
                                                state = 1;
                                                break;
                                            case (Char)0x32:
                                                state = 2;
                                                break;
                                            case (Char)0x33:
                                                state = 3;
                                                break;
                                            case (Char)0x34:
                                                state = 4;
                                                break;
                                            case (Char)0x35:
                                                state = 5;
                                                break;
                                            default:
                                                state = -1;
                                                break;
                                        }
                                        }
                                        if (state != -1)
                                        {
                                            OnBluetoothStateChanged(this, (BluetoothState)state);
                                        }
                                }
                                //Check Pin Requested
                                if (response.IndexOf("+INPIN") > -1)
                                {
                                    // EDUARDO : Needs testing
                                    OnPinRequested(this);
                                }
                                
                                if (response.IndexOf("+RTINQ") > -1)
                                {
                                    //RoSchmi: function was not tested, assume that it does not work
                                    atCommand = "+RTINQ=";
                                    //String parsing  
                                    first = response.IndexOf(atCommand) + atCommand.Length;
                                    try
                                    {
                                        mid = response.IndexOf(";", first);
                                    }
                                    catch
                                    {
                                    }
                                    try
                                    {
                                        last = response.IndexOf("\r", first);
                                    }
                                    catch
                                    {
                                    }
                                    string address = "No address";
                                    try
                                    {
                                        address = ((response.Substring(first, mid - first)).Trim());
                                    }
                                    catch
                                    {
                                    }
                                    string name = "No name";
                                    try
                                    {
                                        name = (response.Substring(mid + 1, last - mid));
                                    }
                                    catch
                                    {
                                    }

                                       OnDeviceInquired(this, address, name);
                                       //Debug.Print("Add: " + address + ", Name: " + name );
                                   }
                                   // Added by RoSchmi
                                   if ((response.IndexOf("OK") > -1) | (response.IndexOf("ERROR") > -1))
                                   {
                                       // If the text OK or ERROR is received the first time, we see that
                                        if (!baudrate_found)  // we have a working baudrate and we release AutoResetEvent
                                        {
                                            Wait_For_Baudrates_Match.Set();
                                        }
                                    }
                                    if (ReadMode_ByteArray)
                                    {
                                        BufLenAdd = 0;
                                        if (WritePtr >= ReadPtr)
                                        {
                                            BufLenAdd = RingBuffer.Length;
                                        }
                                        if ((ReadPtr + bytesToSend) <= RingBuffer.Length)
                                        {
                                            OnDataByteArrayReceived(this, RingBuffer, ReadPtr, bytesToSend);
                                        }
                                        else
                                        {
                                            OnDataByteArrayReceived(this, RingBuffer, ReadPtr, RingBuffer.Length - ReadPtr);
                                            OnDataByteArrayReceived(this, RingBuffer, 0, bytesToSend - (RingBuffer.Length - ReadPtr));
                                        }
                                        Thread.Sleep(eventDelay);
                                    }
                                    else
                                    {
                                       OnDataReceived(this, response);
                                    }
                                    if ((ReadPtr + (bytesToSend - 1)) >= RingBuffer.Length)
                                    {
                                        ReadPtr = ((bytesToSend -1)  - (RingBuffer.Length - ReadPtr)) + 1;
                                    }
                                    else
                                    {
                                        ReadPtr = ReadPtr + bytesToSend;
                                    }
                                    }
                                    
                                    Thread.Sleep(eventDelay);  
                                }  
                       }   // Not (ReadMode_ByteArray && FastReadMode)
                   
                   Thread.Sleep(1);  
               }  // End While Loop
        }   

            private int sendDisplacement()
            {
            // Here we search the displacement of the next LineFeed character (0x0A) 
            // from ReadPtr in RingBuffer
            // when it is done, we return the displacement in LF_Offset
            // when there was no LineFeed in (ReadChunk * 2) bytes or when there came no Linefeed in 50 cycles
            // we return the Offset of the last read byte in the ringbuffer
            // returns with -1 if no bytes are to be read from RingBuffer
           
            LF_Offset = -1;            
            if (WritePtr == ReadPtr)  // RingBuffer is empty
            {
                return LF_Offset;
            }

            //*****************************************************************************************
            if (ReadPtr < WritePtr)
            {
                LF_Offset = Array.IndexOf(RingBuffer, 0x0A, ReadPtr);
                if (LF_Offset != -1)
                {
                    LF_Offset -= ReadPtr;
                    if ((ReadPtr + LF_Offset) >= WritePtr)
                    {
                        if (((WritePtr - ReadPtr) > (ReadChunk * 2)) || (timeOutCtr > 50))
                        {
                            LF_Offset = (WritePtr - ReadPtr) - 1;
                            timeOutCtr = 0;    // free contents of RingBuffer
                        }                     // if no 0x0A in (ReadChunk * 2) bytes or timeOutCtr > 50
                        else
                        {
                            timeOutCtr++;
                            LF_Offset = -1;
                        }
                        return LF_Offset;
                    }
                    else
                    {
                        timeOutCtr = 0;
                        return LF_Offset;
                    }
                }
                else     // no 0x0A was found
                {
                    if (((WritePtr - ReadPtr) > (ReadChunk * 2)) || (timeOutCtr > 50))
                    {
                        LF_Offset = (WritePtr - ReadPtr) - 1;
                        timeOutCtr = 0;      // free contents of RingBuffer
                    }                       // if no 0x0A in (ReadChunk * 2) bytes or timeOutCtr > 50
                    else
                    {
                        timeOutCtr++;
                        LF_Offset = -1;
                    }
                    return LF_Offset;
                }
            }
            //***************************************************************************************
            if (ReadPtr > WritePtr) // Not (ReadPtr < WritePtr) 
            {
                LF_Offset = Array.IndexOf(RingBuffer, 0x0A, ReadPtr);
                if (LF_Offset != -1)          // Found in upper Part of RingBuffer
                {
                    LF_Offset -= ReadPtr;
                    timeOutCtr = 0;
                    return LF_Offset;
                }
                else                         // Not found in upper Part of RingBuffer
                {
                    LF_Offset = Array.IndexOf(RingBuffer, 0x0A, 0);
                    if (LF_Offset != -1)
                    {
                        if (LF_Offset < WritePtr)
                        {
                            LF_Offset += (RingBuffer.Length - ReadPtr);
                            timeOutCtr = 0;
                            return LF_Offset;
                        }
                        else
                        {
                            if ((((RingBuffer.Length - ReadPtr) + WritePtr) > (ReadChunk * 2)) | (timeOutCtr > 50))
                            {
                                LF_Offset = (((RingBuffer.Length - ReadPtr) - 1) + WritePtr) - 1;
                                timeOutCtr = 0;     // free contents of RingBuffer 
                            }                       // if no 0x0A in (ReadChunk * 2) bytes or timeOutCtr > 50
                            else
                            {
                                timeOutCtr++;
                                LF_Offset = -1;
                            }
                            return LF_Offset;
                             
                        }
                    }
                    else    // not found 0x0A at all
                    {
                        if (((RingBuffer.Length - ReadPtr + WritePtr) > (ReadChunk * 2)) || (timeOutCtr > 50))
                        {
                            LF_Offset = (((RingBuffer.Length - ReadPtr) - 1) + WritePtr) - 1;
                            timeOutCtr = 0;         // free contents of RingBuffer
                        }                           // if no 0x0A in (ReadChunk * 2) bytes or timeOutCtr > 50
                        else
                        {
                            timeOutCtr++;
                            LF_Offset = -1;
                        }
                        return LF_Offset;
                    }
                }
            }
                return -1;   
            }

            #region DELEGATES AND EVENTS
            #region Bluetooth State Changed
            /// <summary>
            /// Represents the delegate used for the <see cref="BluetoothStateChanged"/> event.
            /// </summary>
            /// <param name="sender">The object that raised the event.</param>
            /// <param name="btState">Current state of the Bluetooth module</param>
            public delegate void BluetoothStateChangedHandler(Bluetooth sender, BluetoothState btState);
            /// <summary>
            /// Event raised when the bluetooth module changes its state.
            /// </summary>
            public event BluetoothStateChangedHandler BluetoothStateChanged;
            private BluetoothStateChangedHandler onBluetoothStateChanged;

            /// <summary>
            /// Raises the <see cref="BluetoothStateChanged"/> event.
            /// </summary>
            /// <param name="sender">The object that raised the event.</param>  
            /// <param name="btState">Current state of the Bluetooth module</param>
            protected virtual void OnBluetoothStateChanged(Bluetooth sender, BluetoothState btState)
            {
                if (onBluetoothStateChanged == null) onBluetoothStateChanged = new BluetoothStateChangedHandler(OnBluetoothStateChanged);
                if (Program.CheckAndInvoke(BluetoothStateChanged, onBluetoothStateChanged, sender, btState))
                {
                    BluetoothStateChanged(sender, btState);
                }
            }
            #endregion
            
            #region DataReceived
            /// <summary>
            /// Represents the delegate used for the <see cref="DataReceived"/> event.
            /// </summary>
            /// <param name="sender">The object that raised the event.</param>
            /// <param name="data">Data received from the Bluetooth module</param>
            public delegate void DataReceivedHandler(Bluetooth sender, string data);
            /// <summary>
            /// Event raised when the bluetooth module changes its state.
            /// </summary>
            public event DataReceivedHandler DataReceived;
            private DataReceivedHandler onDataReceived;

            /// <summary>
            /// Raises the <see cref="DataReceived"/> event.
            /// </summary>
            /// <param name="sender">The object that raised the event.</param>  
            /// <param name="data">Data string received by the Bluetooth module</param>
            protected virtual void OnDataReceived(Bluetooth sender, string data)
            {
               // if (onDataReceived == null) onDataReceived = new DataReceivedHandler(OnDataReceived);
               // commented out: instance of DataByteArrayReceivedHandler is created in the constructor of Bluetooth.cs
                if (Program.CheckAndInvoke(DataReceived, onDataReceived, sender, data))
                {
                        DataReceived(sender, data);
                }
            }

            // Added by RoSchmi Delegate to transmit data as ByteArray
            public delegate void DataByteArrayReceivedHandler(Bluetooth sender, byte[] data, int startIndex, int ByteCount);
            /// <summary>
            /// Raises the <see cref="DataByteArrayReceived"/> event.
            /// </summary>
            public event DataByteArrayReceivedHandler DataByteArrayReceived;
            private DataByteArrayReceivedHandler onDataByteArrayReceived;

            /// <summary>
            /// Raises the <see cref="DataByteArrayReceived"/> event.
            /// </summary>
            /// <param name="sender">The object that raised the event.</param>  
            /// <param name="data">Data Byte Array received by the Bluetooth module</param>
            /// <param name="startIndex">StartIndex</param>
            /// <param name="ByteCount">ByteCount</param>
            protected virtual void OnDataByteArrayReceived(Bluetooth sender, byte[] data, int startIndex, int ByteCount)
            {
                //  if (onDataByteArrayReceived == null) onDataByteArrayReceived = new DataByteArrayReceivedHandler(OnDataByteArrayReceived);
                //  commented out: instance of DataByteArrayReceivedHandler is created in the constructor of Bluetooth.cs

                if (ByteCount > 0)
                {
                    if (!fastReadMode)
                    {
                        byte[] ByteArraySendData = new byte[ByteCount];
                        Array.Copy(data, startIndex, ByteArraySendData, 0, ByteCount);
                        if (Program.CheckAndInvoke(DataByteArrayReceived, onDataByteArrayReceived, sender, ByteArraySendData, 0, ByteCount))
                        {
                            DataByteArrayReceived(sender, ByteArraySendData, 0, ByteCount);
                        }
                    }
                    else
                    {

                        if (Program.CheckAndInvoke(DataByteArrayReceived, onDataByteArrayReceived, sender, data, startIndex, ByteCount))
                        {
                            DataByteArrayReceived(sender, data, startIndex, ByteCount);
                        }
                    }
                }
                
            }
            // End added by RoSchmi

            #endregion
            #region PinRequested
            /// <summary>
            /// Represents the delegate used for the <see cref="PinRequested"/> event.
            /// </summary>
            /// <param name="sender">The object that raised the event.</param>
            public delegate void PinRequestedHandler(Bluetooth sender);
            /// <summary>
            /// Event raised when the bluetooth module changes its state.
            /// </summary>
            public event PinRequestedHandler PinRequested;
            private PinRequestedHandler onPinRequested;

            /// <summary>
            /// Raises the <see cref="PinRequested"/> event.
            /// </summary>
            /// <param name="sender">The object that raised the event.</param>  
            protected virtual void OnPinRequested(Bluetooth sender)
            {
                if (onPinRequested == null) onPinRequested = new PinRequestedHandler(OnPinRequested);
                if (Program.CheckAndInvoke(PinRequested, onPinRequested, sender))
                {
                    PinRequested(sender);
                }
            }
            #endregion
            #endregion

            #region DeviceInquired
            /// <summary>
            /// Represents the delegate used for the <see cref="DeviceInquired"/> event.
            /// </summary>
            /// <param name="sender">The object that raised the event.</param>
            /// <param name="macAddress">MAC Address of the inquired device</param>
            /// <param name="name">Name of the inquired device</param>
            public delegate void DeviceInquiredHandler(Bluetooth sender, string macAddress, string name);
            /// <summary>
            /// Event raised when the bluetooth module changes its state.
            /// </summary>
            public event DeviceInquiredHandler DeviceInquired;
            private DeviceInquiredHandler onDeviceInquired;

            /// <summary>
            /// Raises the <see cref="PinRequested"/> event.
            /// </summary>
            /// <param name="sender">The object that raised the event.</param>  
            /// <param name="macAddress">MAC Address of the inquired device</param>
            /// <param name="name">Name of the inquired device</param>
            protected virtual void OnDeviceInquired(Bluetooth sender, string macAddress, string name)
            {
                if (onDeviceInquired == null) onDeviceInquired = new DeviceInquiredHandler(OnDeviceInquired);
                if (Program.CheckAndInvoke(DeviceInquired, onDeviceInquired, sender, macAddress, name))
                {
                    DeviceInquired(sender, macAddress, name);
                }
            }
            #endregion
            private object _lock = new Object();

            private Client _client;
        /// <summary>
        /// Sets Bluetooth module to work in Client mode.
        /// </summary>
            public Client ClientMode
            {
                get
                {
                    lock (_lock)
                    {
                        if (_host != null) throw new InvalidOperationException("Cannot use both Client and Host modes for Bluetooth module");
                        if (_client == null) _client = new Client(this);
                        return _client;
                    }
                }
            }

            private Host _host;
        /// <summary>
        /// Sets Bluetooth module to work in Host mode.
        /// </summary>
            public Host HostMode
            {
                get
                {
                    lock (_lock)
                    {
                        if (_client != null) throw new InvalidOperationException("Cannot use both Client and Host modes for Bluetooth module");
                        if (_host == null) _host = new Host(this);
                        return _host;
                    }
                }
            }

        /// <summary>
        /// Sets the device name as seen by other devices
        /// </summary>
        /// <param name="name">Name of the device</param>
            public void SetDeviceName(string name)
            {
                this.serialPort.Write("\r\n+STNA=" + name + "\r\n");
            }

            /// <summary>
            /// Switch the device to the directed speed
            /// </summary>
            /// <param baud="number">Name of the device</param>
            public void SetDeviceBaud(long baud)
            {
                
                string cmd = "";
                
                switch (baud)
                {
                    case 9600: 
                        cmd = "9600";
                        break;
                    case 19200:
                        cmd = "19200";
                        break;
                    case 38400:
                        cmd = "38400";
                        break;
                    case 57600:
                        cmd = "57600";
                        break;
                    case 115200:
                        cmd = "115200";
                        break;
                    case 230400:
                        cmd="230400";
                        break;
                    case 460800:
                        cmd="460800";
                        break;
                    default:
                        cmd="";
                        break;
                }
                
                if (cmd != "")
                    this.serialPort.Write("\r\n+STBD=" + cmd + "\r\n");

                

                //todo: check it is working?! Probably should check the return code and do something about it. in the meantime,
                Thread.Sleep(1000);  
            }
          
            /// <summary>
            /// Sets the PIN code for the Bluetooth module
            /// </summary>
            /// <param name="pinCode"></param>
            public void SetPinCode(string pinCode)
            {
                this.serialPort.Write("\r\n+STPIN=" + pinCode +"\r\n");
            }


            // Added by RoSchmi

            /// <summary>
            /// Permit Auto-connect 
            /// </summary>
            public void PermitAutoConnect()
            {
                //Debug.Print("Message from Class Buetooth: Permit auto-connect");
                this.serialPort.Write("\r\n+STAUTO=1\r\n");
            }
            /// <summary>
            /// Auto-connect forbidden
            /// </summary>
            public void DisableAutoConnect()
            {
                //Debug.Print("Message from Class Buetooth: Disable auto-connect");
                this.serialPort.Write("\r\n+STAUTO=0\r\n");
            }
            /// <summary>
            /// Permit paired device to connect me
            /// </summary>
            public void PermitBeConnected()
            {
                //Debug.Print("Message from Class Bluetooth: Permit be connected");
                this.serialPort.Write("\r\n+STOAUT=1\r\n");
            }
            /// <summary>
            /// Do not permit paired device to connect me
            /// </summary>
            public void DisableBeConnected()
            {
                //Debug.Print("Message from Class Bluetooth: Disable be connected");
                this.serialPort.Write("\r\n+STOAUT=0\r\n");
            }

            /// <summary>
            /// Permit Auto-reconnect after getting out of range
            /// </summary>
            public void PermitAutoReconnect_LostConnection()
            {
                // Needs to be tested
                Debug.Print("Message from Class Bluetooth: Permit AutoReconnect after getting out of range");
                this.serialPort.Write("\r\n+LOSSRECONN=1\r\n");
            }

            /// <summary>
            /// Do not permit Auto-reconnect after getting out of range
            /// </summary>
            public void DisableAutoReconnect_LostConnection()
            {
                // Needs to be tested
                Debug.Print("Message from Class Bluetooth: Disable AutoReconnect after getting out of range");
                this.serialPort.Write("\r\n+LOSSRECONN=0\r\n");
            }

            /// <summary>
            /// Disable ECHO
            /// </summary>
            public void DisableECHO()
            {
                Debug.Print("Disable ECHO");
                this.serialPort.Write("\r\n+STECHO=0\r\n");
            }

            /// <summary>
            /// Enable ECHO
            /// </summary>
            public void EnableECHO()
            {
                Debug.Print("Enable ECHO");
                this.serialPort.Write("\r\n+STECHO=1\r\n");
            }

            // End added by RoSchmi

        /// <summary>
        /// Client functionality for the Bluetooth module
        /// </summary>
            public class Client
            {
                private Bluetooth bluetooth;
                internal Client(Bluetooth bluetooth)
                {
                    Debug.Print("Client Mode");
                    this.bluetooth = bluetooth;
                    bluetooth.serialPort.Write("\r\n+STWMOD=0\r\n");
                }

                /// <summary>
                /// Enters pairing mode
                /// </summary>
                public void EnterPairingMode()
                {
                    Debug.Print("Enter Pairing Mode");
                    bluetooth.serialPort.Write("\r\n+INQ=1\r\n");

                }

                // Added by RoSchmi and Duke Nukem

                /// <summary>
                /// Exits pairing mode
                /// </summary>
                public void ExitPairingMode()
                {
                    Debug.Print("Exit Pairing Mode");
                    bluetooth.serialPort.Write("\r\n+INQ=0\r\n");

                }

                // End added bei RoSchmi

                /// <summary>
                /// Inputs pin code
                /// </summary>
                /// <param name="pinCode">Module's pin code. Default: 0000</param>
                public void InputPinCode(string pinCode)
                {
                    Debug.Print("Inputting pin: " + pinCode);
                    bluetooth.serialPort.Write("\r\n+RTPIN=" + pinCode + "\r\n");
                }

                /// <summary>
                /// Closes current connection. Doesn't work yet.
                /// </summary>
                public void Disconnect()
                {
                    Debug.Print("Disconnection is not working...");
                    //NOT WORKING
                    // Documentation states that in order to disconnect, we pull PIO0 HIGH,
                    // but this pin is not available in the socket... (see schematics)
                }

                /// <summary>
                /// Sends data through the connection.
                /// </summary>
                /// <param name="message">String containing the data to be sent</param>
                public void Send(string message)
                {
                    //Debug.Print("Sending string via bluetooth: .........");
                    bluetooth.serialPort.Write(message);
                    bluetooth.serialPort.Flush();
                }

                //Added by RoSchmi

                /// <summary>
                /// Sends data through the connection.
                /// </summary>
                /// <param name="byteArray">Byte Array containing the data to be sent</param>
                ///
                public void Send(byte[] byteArray)
                {
                    //Debug.Print("Sending byteArray via bluetooth: .........");
                    bluetooth.serialPort.Write(byteArray);
                   
                }
                // End Added by RoSchmi

                /// <summary>
                /// Sends data through the connection.
                /// </summary>
                /// <param name="message">String containing the data to be sent</param>
                ///
                public void SendLine(string message)
                {
                    Debug.Print("Sending: " + message);
                    bluetooth.serialPort.WriteLine(message);
                }
            }

        /// <summary>
        /// Implements the host functionality for the Bluetooth module
        /// </summary>
            public class Host
            {
                private Bluetooth bluetooth;
                internal Host(Bluetooth bluetooth)
                {
                    Debug.Print("Host mode");
                    this.bluetooth = bluetooth;
                    bluetooth.serialPort.Write("\r\n+STWMOD=1\r\n");
                }
                
                /// <summary>
                /// Starts inquiring for devices
                /// </summary>
                public void InquireDevice()
                {
                    Debug.Print("Inquiring device");
                    bluetooth.serialPort.Write("\r\n+INQ=1\r\n");
                    
                }

                //Added by RoSchmi and Duke Nukem

                /// <summary>
                /// Stops inquiring for devices
                /// </summary>
                public void StopInquireDevice()
                {
                    Debug.Print("End Inquiring for devices");
                    bluetooth.serialPort.Write("\r\n+INQ=0\r\n");

                }

                //End Added by RoSchmi

                /// <summary>
                /// Makes a connection with a device using its MAC address.
                /// </summary>
                /// <param name="macAddress">MAC address of the device</param>
                public void Connect(string macAddress)
                {
                    Debug.Print("Connecting to: " + macAddress);
                    bluetooth.serialPort.Write("\r\n+CONN="+macAddress+"\r\n");
                }

                /// <summary>
                /// Inputs the PIN code.
                /// </summary>
                /// <param name="pinCode">PIN code. Default 0000</param>
                public void InputPinCode(string pinCode)
                {
                    Debug.Print("Inputting pin: " + pinCode);
                    bluetooth.serialPort.Write("\r\n+RTPIN=" + pinCode + "\r\n");
                }

                /// <summary>
                /// Closes the current connection. Doesn't work yet.
                /// </summary>
                public void Disconnect()
                {
                    Debug.Print("Disconnection is not working...");
                    //NOT WORKING
                    // Documentation states that in order to disconnect, we pull PIO0 HIGH,
                    // but this pin is not available in the socket... (see schematics)
                }
            }
        }
    }





#20

Program.cs



// Copyright RoSchmi 2014, License: Apache 2.0
// The class Bluetooth.cs in this application is driver for the GHI Bluetooth Module
// The class can be used in other Gadgeteer Mainboards. It was tested for Spider, Cerbuino Bee, Cobra-2 and Raptor
// In this application for Spider the Bluetooth-Module is connected to Socket 8, the GHI Button-Module to Socket 11
// and optinally an rs232 Module on Socket 1
// The application was created on Visual Studio 2012 Express, NETMF Version 4.3, GHI SDK Version 2014 R2
// 
// When the application is deployed and started, the LEDs on the Bluetooth Module should blink alternating blue and red.
// If they do not blink blue and red, press the Button Module to enter pairing mode.
// Then the pairing with your Windows PC should be done according to your Windows Version. As Pairing code enter "0000".
// After successful pairing you have look, which serial ports are used for for the Bluetooth connection by your PC
// Then you can start e.g. Teraterm in Tab "File" open a new serial connectin with one of the two serial ports that are
// used for the bluetooth connection by your PC (one of the two should work)
// If the connection is established you'll receive a Message: "Hello from TinCLR, Message Nr. xx" every second
//
// Instead of using serial ports you can use the a connection through the 32feet.net library as shown in my
// GHI CodeShare entry "FEZ/PC Bluetooth File Transfer Server/Client"

// Note:
// *******************  Reference: Gadgeteer.Serial  must be added   *****************************

using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Touch;
using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using GTI = Gadgeteer.SocketInterfaces;


using Gadgeteer.Modules.GHIElectronics;
using Gadgeteer.Modules.RoSchmi;

namespace Bluetooth_Pairing_Test
{
    public partial class Program
    {
            //**********    Presets:  Parameter to be changed by users  ***************************
            
            const string MyDeviceName = "MySpider";   // Device Name
            const string MyPinCode = "0000";            // Pin Code
            const int MySocketNumber = 8;               // The SocketNumber of the mainboard to which the BT-Module is connected
            const long BT_Device_Baudrate = 38400;      // Baudrate
                                                        // possible baudrates 9600, 19200, 38400, 57600, 115200, 230400, 460800

            const bool ReadMode_ByteArray = true;       // false: data are received as strings -Event: bluetooth_DataReceived
                                                        // true: data are received as byte array-Event: bluetooth_DataByteArrayReceived

            const bool FastReadMode = true;             // true: switch to transmit without parsing
                                                        // false: data are always parsed for BT-module messages

            const int MyEventDelay = 20;                // Choose higher value if data received events queue up ( 20 = standard)
                                                        // has no effect in ReadMode_ByteArray Mode in combination with FastReadMode 

            const int SendInterval = 1000;              // In this time interval  we send a message to the BT-Module

            //**************** End Parameter to be changed by user ***************************

            static private Bluetooth bluetooth;
            static private Bluetooth.Client client;

            static int MessageCounter = 0;    // Counter to count the sent messages

            static long BytesTransferred = 0;
            static long LastBytesTransferred = 0;
            static long baudrate = 0;
            static long events = 0;
            static long lastevents = 0;
            static long eventspersec = 0;
            static long showEvent = 0;

            byte[] datadrain = new byte[2000];  // Dummy, here we can put the received data
            
            // timerSendData is used to fire in interval to send data to the BT-Module
            GT.Timer timerSendData;

            // timer, used to calculate statistics every 2 seconds (not needed in applications)
            GT.Timer CalculateBaudrate;
         
            // timerEnterPairing is used to enter pairing mode automatically
            GT.Timer timerEnterPairing;

            string dataLine1 = null;      // used to process incoming data in eventhandler: bluetooth_DataReceived (as String)
            string dataLine2 = null;      // used to process incoming data in eventhandler: bluetooth_DataByteArrayReceived (as Byte Array)
            byte[] ReceivedBytes;         // used to process incoming data in eventhandler: bluetooth_DataReceived (as String)
            SerialBuffer mySerialBuffer;  // used to connect incoming data chunks and split after LineFeed (0x0A)

            #region ProgramStarted()
            // This method is run when the mainboard is powered up or reset.   
            void ProgramStarted()
            {
                Debug.Print("Program Started");

                // Event handler for button to enter pairing mode
                button.ButtonPressed += new Button.ButtonEventHandler(button_ButtonPressed);

                // Set a timer to enter pairing mode after 3 seconds
                timerEnterPairing = new GT.Timer(3000,GT.Timer.BehaviorType.RunOnce);
                timerEnterPairing.Tick +=new GT.Timer.TickEventHandler(timerEnterPairing_Tick);

                // Set a timer to send data to the BT-Module in intervals
                timerSendData = new GT.Timer(SendInterval);
                timerSendData.Tick += new GT.Timer.TickEventHandler(timerSendData_Tick);
                timerSendData.Stop();

                CalculateBaudrate = new GT.Timer(2000, GT.Timer.BehaviorType.RunContinuously);
                CalculateBaudrate.Tick += new GT.Timer.TickEventHandler(CalculateBaudrate_Tick);
                CalculateBaudrate.Start();


                // define a bluetooth module running on socket: "MySocketNumber", baudrate: "BT_Device_Baudrate"
                Debug.Print("Program Message: Initialize Bluetooth module on Port " + MySocketNumber.ToString() 
                             + " Baudrate: " + BT_Device_Baudrate.ToString());
                bluetooth = new Bluetooth(MySocketNumber, BT_Device_Baudrate);

                bluetooth.EventDelay = MyEventDelay;  // Choose higher value in "Presets" if data received events queue up ( 20 = standard)
                                                      // has no effect in ReadMode_ByteArray Mode in combination with FastReadMode 

                // Set the Mode to receive data as Strings or as Byte Array depending on the settings in "Presets"
                bluetooth.SetReadMode_ByteArray(ReadMode_ByteArray);

                // Set up eventhandler for state changes
                bluetooth.BluetoothStateChanged += new Bluetooth.BluetoothStateChangedHandler(bluetooth_BluetoothStateChanged);

                // Set up eventhandler to receive data from the Bluetooth module as Strings or as Byte Arrays (only one is needed)
                bluetooth.DataReceived += new Bluetooth.DataReceivedHandler(bluetooth_DataReceived);
                bluetooth.DataByteArrayReceived += new Bluetooth.DataByteArrayReceivedHandler(bluetooth_DataByteArrayReceived);

                Debug.Print("Program Message: Set Bluetooth module to Client Mode" + "\r\n");
                client = bluetooth.ClientMode;
                Thread.Sleep(200);

                Debug.Print("Program Message: Set Device Name: " + MyDeviceName + "\r\n");
                bluetooth.SetDeviceName(MyDeviceName);
                Thread.Sleep(2000);                     // time was not tested

                Debug.Print("Program Message: Set Device Pincode" + "\r\n");
                bluetooth.SetPinCode(MyPinCode);
                Thread.Sleep(2000);                     // time was not tested

                /*
                Debug.Print("Program Message: Set BT-Device to: Disable Auto-connect " + "\r\n");
                bluetooth.DisableAutoConnect();
                Thread.Sleep(200);
                */
                
                Debug.Print("Program Message: Set BT-Device to: Enable Auto-connect " + "\r\n");
                bluetooth.PermitAutoConnect();
                Thread.Sleep(200);                      // time was not tested
                
                Debug.Print("Program Message: Set BT-Device to: PermitBeConnected" + "\r\n");
                bluetooth.PermitBeConnected();
                Thread.Sleep(200);                      // time was not tested

                bluetooth.serialPort.DiscardInBuffer();
                bluetooth.serialPort.DiscardOutBuffer();
                Thread.Sleep(200);

                mySerialBuffer = new SerialBuffer(256);

                timerSendData.Start();
                timerEnterPairing.Start();
            }
            #endregion

            #region CalculateBaudrate_Tick  (this is needed only to calaculate statistics)
            void CalculateBaudrate_Tick(GT.Timer timer)
            {
                baudrate = ((BytesTransferred - LastBytesTransferred) / 2) * 10;
                LastBytesTransferred = BytesTransferred;
                eventspersec = (events - lastevents) / 2;
                lastevents = events;
            } 
            #endregion


            #region timerSendData_Tick   Sends a message over the Bluetooth Connection
            void timerSendData_Tick(GT.Timer timer)
            {
                //Debug.Print("Program Message: ____________________________timerSendData ticked");
                // check to see that the bluetooth module is connected, and if so send a message over the connection
                if (bluetooth.IsConnected)
                {
                    //Debug.Print("Program Message: BT is connected, so I send the message: " + "Hello from TinyClr, Message No.: " + MessageCounter.ToString());

                    client.Send("Hello from TinyClr, Message No.: " + MessageCounter.ToString() + "\r\n");
                    MessageCounter++;
                }
                else
                {
                    Debug.Print("Program message: BT is not connected, cannot send message");
                }
            }
            #endregion

            #region button_ButtonPressed    Enter Pairing Mode
            void button_ButtonPressed(Button sender, Button.ButtonState state)
            {
                // check to see that the bluetooth module is connected, and if so do nothing
                if (bluetooth.IsConnected)
                {
                    Debug.Print("Program Message: You pressed the button but BT was connected, so not activating pairing mode");
                }
                // otherwise, just go into first-time pairing mode.
                else
                {
                    Debug.Print("Program Message: You pressed the button and BT was not connected, so I go to pairing mode");
                    client.EnterPairingMode();
                }
            }
            #endregion

            #region timerEnterPairing_Tick    Enter Pairing Mode
            void timerEnterPairing_Tick(GT.Timer timer)
            {
                if (!bluetooth.IsConnected)
                {
                    Debug.Print("Enter pairing mode by timer event");
                    client.EnterPairingMode();
                }
            }
            #endregion

            // You have the choice to receive the data as strings or as ByteArrays. You need only one

            #region  Eventhandler --  Receive data as Strings
            // Select this output mode with the  bluetooth.SetReadMode_ByteArray(false) command
            private void bluetooth_DataReceived(Bluetooth sender, string data)
            {
               ReceivedBytes = System.Text.UTF8Encoding.UTF8.GetBytes(data);
               mySerialBuffer.LoadSerial(ReceivedBytes, 0, ReceivedBytes.Length);

                // To see the chunks of data we can activate this Debug.Print
                //Debug.Print("\r\n Program Message: Received chunk of data (String Mode). Byte-Count: " + data.Length.ToString() + " Data: " + HexEncoding.ToString(ReceivedBytes, 0, ReceivedBytes.Length) + "\r\n" + data + "\r\n");

                
                while ((dataLine1 = mySerialBuffer.ReadLine()) != null)
                {
                   Debug.Print("Line Received: " + dataLine1);
                   

                    // parse the data sentence here if needed
                }
               
            }
            #endregion

            #region  Eventhandler --  Receive data as Byte Arrays
            // Select this output mode with the  bluetooth.SetReadMode_ByteArray(true) command
            void bluetooth_DataByteArrayReceived(Bluetooth sender, byte[] data, int startIndex, int ByteCount)
            {
                BytesTransferred += ByteCount;
                events++;
                Array.Copy(data, startIndex, datadrain, 0, ByteCount);  // Dummy for the time it takes to get the data (they are not valid for a long time)
                

                // *************************************************************************************
                // if we want to see from time to time a short segment of the data, we send them over rs232
                // we cannot see longer segments as we get buffer overflows
                /*
                if ((events > showEvent + 50) && (events < showEvent + 53))  // arbitrary values to show some transmitted data
                {
                    mySerialBuffer.LoadSerial(data, startIndex, ByteCount);
                    showEvent = events;
                }
                */
                // ************************************************************************************
                
                if (ByteCount < 100)   // for short messages we send it over rs232
                {
                    mySerialBuffer.LoadSerial(data, startIndex, ByteCount);
                }
                else                  // for high speed data we only send the statistics
                {

                    //rs232.serialPort.Write("Bytes Transferred: " + BytesTransferred.ToString() + "  Bytes per event: " + ByteCount.ToString() + " Estimated Baudrate: " + baudrate.ToString() + " Received Events per sec:  " + eventspersec.ToString() + "\r\n");
                }
                while ((dataLine2 = mySerialBuffer.ReadLine()) != null)
                {
                    // If we have a RS232 module connected we can send the received data to another PC
                    Debug.Print(dataLine2 + "\r\n");
                    //rs232.serialPort.Write(dataLine2 + "\r\n");

                    // parse the data sentence here if needed
                }
            }
            #endregion

            #region  Eventhandler signalizing that the BTSTATE of the Bluetooth module has changed
            void bluetooth_BluetoothStateChanged(Bluetooth sender, Bluetooth.BluetoothState btState)
            {
                // here the bluetooth module's state has changed. First, just debug print the value so we know what is happening
                Debug.Print("New state:" + btState.ToString());

                // If the state is now "connected", we can do stuff over the link.
                if (btState == Bluetooth.BluetoothState.Connected)
                {
                    Debug.Print("\r\n Program Message: BT-Connection established, BTSTATE: " + btState.ToString() + "\r\n");

                    bluetooth.SetFastReadMode(FastReadMode);  // Set fastReadMode, depending on the flag in presets
                   
                    Thread.Sleep(1000);      // do this to wait for BT module to connect; 
                    client.Send("\r\nConnected to Fez\r\n");
                }
                // if the state is now "disconnected", you might need to stop other processes but for this example we'll just confirm that in the debug output window
                if (btState != Bluetooth.BluetoothState.Connected)
                {
                   // Debug.Print("\r\n" + "Program Message: Bluetooth disconnected, BTSTATE: " +  btState.ToString() + "\r\n");
                }
            }
            #endregion
    }
}