// Change the baud rate. Doesn't take effect until write/reset cycle, so you // can get the "OK" message after changing the setting. BLEMate2::opResult BLEMate2::setBaudRate(unsigned int newSpeed) { // Temp for the string value you'll want to send out to the module. String speedString = ""; // The BC118 doesn't want a nice, human readable string; it wants a 16-bit // unsigned int represented as a string. // Here we'll convert things appropriately from the numeric speed input // (2400, 9600, 19200, 38400, 57600) to a string which the BC118 recognizes // as being the parameter for that string. switch(newSpeed) { case 2400: speedString = "000A"; break; case 9600: speedString = "0028"; break; case 19200: speedString = "004E"; break; case 38400: speedString = "009E"; break; case 57600: speedString = "00EB"; break; default: return INVALID_PARAM; } // Because this doesn't take effect until after a write/reset, stdSetParam() // works perfectly. return stdSetParam("UART", speedString); }
// We need a baud rate setting handler. Let's make one! This is kinda tricksy, // though, b/c the baud rate change takes effect immediately, so the return // string from the baud rate change will be garbled. This will result in a // TIMEOUT_ERROR from that function (after all, the EOL won't be recognized, // since it'll be at the wrong baud rate). So, if we get a TIMEOUT_ERROR from // the module, we'll re-do the command at the new baud rate. If *that* fails. // we can assume something is radically wrong. BC127::opResult BC127::setBaudRate(baudRates newSpeed) { // The BC127 wants a string, but the .begin() functions want an integer. We // need a variable to hold both types. int intSpeed; String stringSpeed; // Convert our enum values into strings the module can use. switch(newSpeed) { case BC127::s9600bps: stringSpeed = "9600"; break; case BC127::s19200bps: stringSpeed = "19200"; break; case BC127::s38400bps: stringSpeed = "38400"; break; case BC127::s57600bps: stringSpeed = "57600"; break; case BC127::s115200bps: stringSpeed = "115200"; break; default: return INVALID_PARAM; } // If we've made it to here, we had a valid input to the function and should // send it off to the set parameter function. intSpeed = atoi(stringSpeed); // So, there are three possibilities here: SUCCESS, MODULE_ERROR, and // TIMEOUT_ERROR. SUCCESS indicates that you just set the baud rate to the // same baud rate which is currently in use; MODULE_ERROR indicates that // something weird happened to the string before it was sent (honestly, after // I'm done hammering the dents out, I can't imagine that coming up), and // TIMEOUT_ERROR indicates one of two things: an actual timeout, OR success // but we couldn't read it b/c the baud rate was broken. Since we're using // the inheritance of the Stream class to manipulate our serial ports, we // can't change the baud rate. The user should probably just interpret // TIMEOUT_ERROR as success, and call it good. return stdSetParam("BAUD", stringSpeed); }
// With the BC118, *scan* is a much more important thing that with the BC127. // It's a "state", and in order to initiate a connection as a central device, // the BC118 *must* be in scan state. // Timeout is not inherent to the scan command, either; that's a separate // parameter that needs to be set. BLEMate2::opResult BLEMate2::BLEScan(unsigned int timeout) { // Let's assume that we find nothing; we'll call that a REMOTE_ERROR and // report that to the user. Should we find something, we'll report success. opResult result = REMOTE_ERROR; String buffer = ""; String addressTemp; String EOL = String("\n\r"); String timeoutString = String(timeout, DEC); stdSetParam("SCNT", timeoutString); for (byte i = 0; i <5; i++) _addresses[i] = ""; _numAddresses = 0; knownStart(); // Now issue the scan command. _serialPort->print("SCN ON\r"); _serialPort->flush(); // We're going to use the internal timer to track the elapsed time since we // issued the command. Bog-standard Arduino stuff. unsigned long loopStart = millis(); // Calculate a timeout value that's a tish longer than the module will // use. This is our catch-all, so we don't sit in this loop forever waiting // for input that will never come from the module. unsigned long loopTimeout = timeout*1300; // Oooookaaaayyy...now the fun part. A state machine that parses the input // from the Bluetooth module! while (loopStart + loopTimeout > millis()) { // Grow the current buffered data, until we receive the EOL string. if (_serialPort->available() >0) { buffer.concat(char(_serialPort->read())); } if (buffer.endsWith(EOL)) { // There are two possibilities for return values: // 1. ERR - indicates a problem with the module. Either we're in the // wrong state to be trying to do this (we're not central, // not idle, or both) or there's a syntax error. // 2. SCN=X 12charaddrxx xxxxxxxxxxxxxxx\n\r // In this case, all we care about is the content from char // 6 to 18. // Note the lack of any kind of completion string! The module just stops // reporting when done, and we'll never know if it doesn't find anything // to report. if (buffer.startsWith("ER")) { return MODULE_ERROR; } else if (buffer.startsWith("SC")) // An address has been found! { // The returned device string looks like this: // scn=? 12charaddrxx bunch of other stuff\n\r // We can ignore the other stuff, and the first stuff, and just // report the address. addressTemp = buffer.substring(6,18); buffer = ""; if (_numAddresses == 0) { _addresses[0] = addressTemp; _numAddresses++; result = SUCCESS; } else // search the list for this address, and append if it's not in // the list and the list isn't too long. { for (byte i = 0; i < _numAddresses; i++) { if (addressTemp == _addresses[i]) { addressTemp = "x"; break; } } if (addressTemp != "x") { _addresses[_numAddresses++] = addressTemp; } if (_numAddresses == 5) return SUCCESS; } } else // buffer is not a valid value { buffer = ""; } } } // result will either have been unchanged (we didn't see anything) and // be REMOTE_ERROR or will have been changed to SUCCESS when we saw our // first address. return result; }
// Of course, we also need some way to return the module to sink mode, if we // want to do that. BC127::opResult BC127::setClassicSink() { return stdSetParam("CLASSIC_ROLE", "0"); }
// In order to set the module as a source for streaming audio out to another // device, you must set the "CLASSIC_ROLE" parameter to 1, then write/reset to // make that setting active. This function handles this parameter setting. BC127::opResult BC127::setClassicSource() { return stdSetParam("CLASSIC_ROLE", "1"); }
BLEMate2::opResult BLEMate2::BLEPeripheral() { return stdSetParam("CENT", "OFF"); }
// Function to put the module into BLE Central Mode. BLEMate2::opResult BLEMate2::BLECentral() { return stdSetParam("CENT", "ON"); }