Driver for the JY-MCU v1.06 HC-06 Bluetooth module.

Dependents:   DISCO-F746NG_rtos_test MbedTableControl

HC06Bluetooth.cpp

Committer:
Weimen Li
Date:
2016-08-08
Revision:
21:cce827364df1
Parent:
20:13283edd1aba

File content as of revision 21:cce827364df1:

/*
 * HC06Bluetooth.cpp
 *
 *  Created on: Jun 4, 2016
 *      Author: Developer
 */

#include <HC06Bluetooth.h>
#include "rtos.h"

/* Static methods used to help configure the Baudrate. */

// WARNING: DO NOT CHANGE THESE VALUES, AS THEY ARE USED TO INDEX INTO AN ARRAY FOR IMPLEMENTATION.
const char* BaudATString[] = {"AT+BAUD1", "AT+BAUD2", "AT+BAUD3", "AT+BAUD4", "AT+BAUD5", "AT+BAUD6", "AT+BAUD7", "AT+BAUD8", "AT+BAUD9", "AT+BAUDA", "AT+BAUDB", "AT+BAUDC"};
const int32_t BaudATReplyLength[] = {6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8, 9};
//const char* BaudATReplyPattern[] = {"OK1200", "OK2400", "OK4800","OK9600","OK19200","OK38400","OK57600","OK115200","OK230400","OK460800","OK921600","OK1382400"};
const int32_t BaudValue[] = {1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 1382400};

/* HC06 Bluetooth Class Implementation: */
HC06Bluetooth::HC06Bluetooth(PinName TX, PinName RX, Baudrate baudrate, void (*lineCallbackFunc) (const char* readString, size_t strlen), void (*charCallbackFunc) (char readChar))
    : btSerialObj(TX, RX), baudrate(baudrate), receiveByteThreadObj(osPriorityRealtime), lineCallbackFunc(lineCallbackFunc), charCallbackFunc(charCallbackFunc)
{
    btSerialObj.baud(BaudValue[baudrate]);

    // Set the interrupt to be called when a byte is received.
    if ((lineCallbackFunc != NULL) || (charCallbackFunc != NULL))
    {
        btSerialObj.attach(this, &HC06Bluetooth::receiveByteISR);
        receiveByteThreadObj.start(this, &HC06Bluetooth::receiveByteThread);
    }
}

void HC06Bluetooth::runSetup(std::string deviceName, std::string PIN)
{
    int numCharsReceived = 0;
    // Detatch the interrupt.
    btSerialObj.attach(NULL);
    /* Sweep through a list of Baud rates until we find the one that the device has previously been set to. */
    bool baudFound = false;
    Timer timeOut;
    timeOut.start();
    // For every baud rate in the list:
    for (volatile int i = 0; (i < END) && (!baudFound); i++)
    {
        // Set the communication baud rate to it.
        btSerialObj.baud(BaudValue[i]);
        // Send the test command "AT" to the device.
        btSerialObj.puts("AT");
        // While the time out has not been reached:
        for(timeOut.reset(); timeOut.read_ms() < 1000; )
        {
            // If the serial object is readable, make sure the read character matches the reply string "OK".
            if (btSerialObj.readable() && !baudFound)
            {
                baudFound = true;
                break;
            }
        }
    }
    // Flush whatever's in the input buffer.
    while(btSerialObj.readable())
    {
        btSerialObj.getc();
    }
    //Overwrite the Baud rate to 115200.
    btSerialObj.puts(BaudATString[baudrate]);
    btSerialObj.baud(BaudValue[baudrate]);
    // Wait for the 8 character reply "OK115200"
    for(numCharsReceived = 0 ; numCharsReceived < BaudATReplyLength[baudrate]; numCharsReceived++)
    {
        //while(!btSerialObj.readable());
        //btSerialObj.getc();
    }
    wait_ms(1000);

    // Set the name of the device.
    btSerialObj.puts(("AT+NAME" + deviceName.substr(0,20)).c_str());
    // Wait for the 6 character reply "OKname"
    for(numCharsReceived = 0 ; numCharsReceived < 6; numCharsReceived++)
    {
        //while(!btSerialObj.readable());
        //btSerialObj.getc();
    }
    wait_ms(1000);

    //Set the password of the device.
    btSerialObj.puts(("AT+PIN" + PIN.substr(0, 4)).c_str());
    // Wait for the 8 character reply "OKsetpin"
    for(numCharsReceived = 0 ; numCharsReceived < 8; numCharsReceived++)
    {
        //while(!btSerialObj.readable());
        //btSerialObj.getc();
    }
    wait_ms(1000);
    // Reattach the interrupt.
    btSerialObj.attach(this, &HC06Bluetooth::receiveByteISR);
}

HC06Bluetooth::~HC06Bluetooth()
{
    // TODO Auto-generated destructor stub
}

void HC06Bluetooth::print(const char* buffer)
{
    // TODO: Code hangs if buffer is too long! Not sure why.
    btSerialObj.puts(buffer);
}

void HC06Bluetooth::println(const char* buffer)
{
    btSerialObj.puts(buffer);
    btSerialObj.putc('\n');
}

void HC06Bluetooth::print(char c)
{
    btSerialObj.putc(c);
}

void HC06Bluetooth::receiveByteISR()
{
    // Get all available characters in the input and place them in the buffer.

    while(btSerialObj.readable())
    {
        dataReceivedBuffer.put((char*) btSerialObj.getc());
    }
}

void HC06Bluetooth::receiveByteThread()
{
    // Now that all characters have been read, process them.
    char receivedChar;
    while(true)
    {
      receivedChar = (uint32_t) dataReceivedBuffer.get().value.p;
        // Call the character callback function if it is not null.
        if (charCallbackFunc != NULL) charCallbackFunc(receivedChar);

        if (lineCallbackFunc != NULL)
        {
            // If the character is a newline or carriage return, then call the line callback function.
            if ((receivedChar == '\n') || (receivedChar == '\r'))
            {
                // Clear whatever was in the toClient buffer before.
                dataReceivedToClient.clear();
                // Copy everything from the queue to the client buffer.
                while(!dataReceivedBufferCopy.empty())
                {
                    dataReceivedToClient.push_back(dataReceivedBufferCopy.front());
                    dataReceivedBufferCopy.pop();
                }
                // Null-terminate the string.
                dataReceivedToClient.push_back('\0');

                // Call the callback function with the toClient buffer.
                lineCallbackFunc(&dataReceivedToClient[0], dataReceivedToClient.size());
            }

            // Otherwise, enqueue it in the copy.
            else
            {
                dataReceivedBufferCopy.push(receivedChar);
            }
        }
    }
}