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

Dependents:   DISCO-F746NG_rtos_test MbedTableControl

Revision:
15:6a0aeaa39291
Parent:
12:5ba022adbbfb
Child:
16:1030b80a28f4
--- a/HC06Bluetooth.h	Wed Aug 03 18:05:49 2016 +0000
+++ b/HC06Bluetooth.h	Wed Aug 03 18:18:05 2016 +0000
@@ -1,74 +1,142 @@
-/**
- * @file HC06Bluetooth.hpp
- * @date June 4th, 2016
- * @author Weimen Li
- * @class HC06Bluetooth
- * @brief This class creates an object representing the HC06 Bluetooth Module
- * The baud rate for the device is configured to be 115200.
+/*
+ * HC06Bluetooth.cpp
+ *
+ *  Created on: Jun 4, 2016
+ *      Author: Developer
  */
 
+#include <HC06Bluetooth.h>
+#include <algorithm>
 
-#ifndef HC06BLUETOOTH_H_
-#define HC06BLUETOOTH_H_
-#include "mbed.h"
-#include <string>
+/* 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), lineCallbackFunc(lineCallbackFunc), charCallbackFunc(charCallbackFunc), dataReceivedBufferPos(0) {
+    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);
+    }
+}
 
-const int dataBufferSize = 256;
-// WARNING: DO NOT CHANGE THESE VALUES, AS THEY ARE USED TO INDEX INTO AN ARRAY FOR IMPLEMENTATION.
-enum Baudrate {B1200, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B921600, B1382400, END};
+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);
 
-class HC06Bluetooth {
-public: // Public methods.
-    /**
-     * @brief Constructor for the HC06_Bluetooth class.
-     * @param TX The pin that the TX line is attached to.
-     * @param RX The pin that the RX line is attached to.
-     * @param deviceName The name that you want your system to be identified as when you connect to it i.e. "Weimen's MAE433Robot"
-     * @param password A 4-digit numeric PIN that you want your device to connect with. It defaults to "1234".
-     * @param lineCallbackFunc The callback function that will be called once a newline character is encountered on the receiving data.
-     * The callback function takes as an argument a string containing the line that has been read.
-     * @remark The callback function is run within within an interrupt service routine, so it should be written to be safe for ISRs.
-     * @param charCallbackFunc A function that will be called once a new character has been read. It should return void and take as an argument
-     * the character that has been read.
-     * @remark The callback function is run within within an interrupt service routine, so it should be written to be safe for ISRs.
-     */
-    HC06Bluetooth(PinName TX, PinName RX, Baudrate baudrate = B115200, void (*lineCallbackFunc) (const char* readString, size_t strlen) = NULL, void (*charCallbackFunc) (char readChar) = NULL);
-    virtual ~HC06Bluetooth();
-    /**
-     * @brief Run the setup routine to configure the device name and the device pin.
-     * @remark: You only need to run this once during the entire time you have the module, since the device name and PIN are saved
-     * by the module itself! However, you may run the function again if you would like to change the deviceName or PIN.
-     * @param deviceName The name of the device, as a string. It must only contain alphanumeric characters - no spaces allowed.
-     * @param PIN The device PIN.
-     */
-    void runSetup(std::string deviceName, std::string PIN = "1234");
-    /**
-     * @brief Print information in buffer to the output.
-     * @param buffer A null-terminated buffer containing the data you want to send.
-     */
-    void print(const char *buffer);
-    /**
-     * @brief Print information in buffer to the output followed by a newline
-     * @param buffer A null-terminated buffer containing the data you want to send.
-     */
-    void println(const char *buffer);
-    /**
-     * @brief Print a character to output.
-     * @param char The character you want to print to output.
-     */
-    void print(char c);
+    //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);
+}
 
-private:
-    RawSerial btSerialObj;
-    Baudrate baudrate;
-    void receiveByteISR();
-    /// Pointer to a callback function the client provides when a line is received.
-    void (*lineCallbackFunc) (const char*, size_t strlen);
-    /// Pointer to a callback function the client provides when a character is received.
-    void (*charCallbackFunc) (char);
-    char dataReceivedBuffer[dataBufferSize];
-    int32_t dataReceivedBufferPos;
-    char dataReceivedBufferCopy[dataBufferSize];
-};
+void HC06Bluetooth::receiveByteISR() {
+    while(btSerialObj.readable()) {
+        // Get the character from the input.
+        char receivedChar = btSerialObj.getc();
+
+        // Call the character callback function if it is not null.
+        if (charCallbackFunc != NULL) {
+            charCallbackFunc(receivedChar);
+        }
 
-#endif /* HC06BLUETOOTH_H_ */
+        if (lineCallbackFunc != NULL) {
+            // If the character is a newline or carriage return, then call the line callback function.
+            if ((receivedChar == '\n') || (receivedChar == '\r')) {
+                // Terminate the buffer with a null character, since that is what strings end with.
+                receivedChar = '\0';
+                dataReceivedBuffer[dataReceivedBufferPos] = receivedChar;
+                dataReceivedBufferPos++;
+                // Copy data from the buffer to a copy.
+                std::copy(dataReceivedBuffer, dataReceivedBuffer + dataReceivedBufferPos, dataReceivedBufferCopy);
+                // Call the callback function.
+                if (lineCallbackFunc != NULL) {
+                    lineCallbackFunc((const char*)dataReceivedBuffer, dataReceivedBufferPos);
+                }
+                // Reset the buffer position.
+                dataReceivedBufferPos = 0;
+            }
+            // Otherwise, just place it in the buffer and move on.
+            else {
+                if (dataReceivedBufferPos < dataBufferSize) {
+                    dataReceivedBuffer[dataReceivedBufferPos] = receivedChar;
+                    dataReceivedBufferPos++;
+                }
+            }
+        }
+    }
+}
+