Bluetooth setup, initial code

This commit is contained in:
Andrei 2017-06-04 15:52:44 +03:00
parent 06b345c9ef
commit e7bc494c53
3 changed files with 346 additions and 0 deletions

View File

@ -0,0 +1,263 @@
#include "main.h"
#include "engine_state.h"
#include "tunerstudio.h"
#include "tunerstudio_io.h"
#include "bluetooth.h"
#include "engine_configuration.h"
#if EFI_BLUETOOTH_SETUP || defined(__DOXYGEN__)
static bool btProcessIsStarted = false;
static bool btProcessIsRunning = false;
static const char *commands[5];
static int numCommands = 0;
static int setBaudIdx = -1;
static char cmdBaud[10];
static char cmdName[30];
static char cmdPin[16];
static const int baudRates[] = { 0, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, -1 };
static const int baudRateIndexList[] = { 4 /*9600*/, 6 /*38400*/, 8 /*115200*/, 7, 5, 3, 2, 1, -1 };
static const int btModuleTimeout = MS2ST(1000);
static ts_channel_s *tsChannel;
static THD_WORKING_AREA(btThreadStack, UTILITY_THREAD_STACK_SIZE);
static thread_t *btThread = NULL;
static thread_reference_t btThreadRef = NULL; // used by thread suspend/resume as a flag
static LoggingWithStorage btLogger("bluetooth");
EXTERN_ENGINE
;
// Main communication code
// We assume that the user has disconnected the software before starting the code.
static void runCommands() {
uint8_t buffer[2];
if (!btProcessIsStarted)
return;
// Store current serial port speed - we're going to change it
int savedSerialSpeed = boardConfiguration->tunerStudioSerialSpeed;
int prevBaudIdx = -1, baudIdx = -1, baudListIdx = 0;
int cmdIdx = 0;
// run all commands
while (true) {
if (baudIdx < 0) {
// try all available baud rates, in order of preference
baudIdx = baudRateIndexList[baudListIdx++];
// we've tried all baud rates?
if (baudIdx < 0)
break;
}
bool restoreAndExit = (cmdIdx >= numCommands || baudIdx < 0);
// if the baud rate is changed, reinit the UART
if (baudIdx != prevBaudIdx || restoreAndExit) {
// deinit UART
if (!stopTsPort(tsChannel)) {
scheduleMsg(&btLogger, "Failed! Cannot restart serial port connection!");
return;
}
chThdSleepMilliseconds(10); // safety
// change the port speed
boardConfiguration->tunerStudioSerialSpeed = restoreAndExit ? savedSerialSpeed : baudRates[baudIdx];
// init UART
startTsPort(tsChannel);
chThdSleepMilliseconds(10); // safety
prevBaudIdx = baudIdx;
}
// exit if all commands were sent
if (restoreAndExit)
break;
// send current command
sr5WriteData(tsChannel, (uint8_t *)commands[cmdIdx], strlen(commands[cmdIdx]));
// waiting for an answer
bool wasAnswer = false;
if (sr5ReadDataTimeout(tsChannel, buffer, 2, btModuleTimeout) == 2) {
wasAnswer = (buffer[0] == 'O' && buffer[1] == 'K');
}
// wait 1 second and skip all remaining response bytes from the bluetooth module
while (true) {
if (sr5ReadDataTimeout(tsChannel, buffer, 1, btModuleTimeout) < 1)
break;
}
if (wasAnswer) {
// if we changed the baud rate
if (commands[cmdIdx] == cmdBaud) {
// this is what we've set
baudIdx = setBaudIdx;
// if we fail somehow, try all other baud rates
baudListIdx = 0;
}
// move to the next command
cmdIdx++;
} else {
// try other baud rate
baudIdx = -1;
}
}
// the connection is already restored to the current baud rate, so print the result
if (cmdIdx == numCommands)
scheduleMsg(&btLogger, "SUCCESS! All commands (%d of %d) passed to the Bluetooth module!", cmdIdx, numCommands);
else
scheduleMsg(&btLogger, "FAIL! Only %d commands (of %d total) were passed to the Bluetooth module!", cmdIdx, numCommands);
}
static THD_FUNCTION(btThreadEntryPoint, arg) {
(void) arg;
chRegSetThreadName("bluetooth thread");
scheduleMsg(&btLogger, "*** Bluetooth module setup procedure ***");
scheduleMsg(&btLogger, "!Warning! Please make sure you're not currently using the BT module for communication (not paired)!");
scheduleMsg(&btLogger, "TO START THE PROCEDURE: PLEASE DISCONNECT YOUR PC COM-PORT FROM THE BOARD NOW!");
scheduleMsg(&btLogger, "After that please don't turn off the board power and wait for ~15 seconds to complete. Then reconnect to the board!");
// now wait
chSysLock();
msg_t msg = chThdSuspendTimeoutS(&btThreadRef, BLUETOOTH_COMMAND_TIMEOUT);
chSysUnlock();
if (msg == MSG_TIMEOUT) {
scheduleMsg(&btLogger, "The Bluetooth module init procedure is cancelled (timeout)!");
return;
} else {
// call this when the thread is resumed (after the disconnect)
btProcessIsRunning = true;
runCommands();
btProcessIsRunning = false;
}
// release the command
btProcessIsStarted = false;
chThdExit(MSG_OK);
}
void bluetoothStart(ts_channel_s *tsChan, bluetooth_module_e moduleType, const char *baudRate, const char *name, const char *pinCode) {
static const char *usage = "Usage: bluetooth_hc06 <baud> <name> <pincode>";
tsChannel = tsChan;
// if a binary protocol uses USB, we cannot init the bluetooth module!
if (!boardConfiguration->useSerialPort) {
scheduleMsg(&btLogger, "Failed! Serial Port connection is disabled!");
return;
}
if (btProcessIsStarted) {
scheduleMsg(&btLogger, "The Bluetooth module init procedure is already started and waiting! To cancel it, run \"bluetooth_cancel\" command!");
return;
}
// todo: add support for other BT module types
if (moduleType != BLUETOOTH_HC_06) {
scheduleMsg(&btLogger, "This Bluetooth module is currently not supported!");
return;
}
numCommands = 0;
// now check the arguments and add other commands:
// 1) baud rate
int baud = (baudRate != NULL) ? atoi(baudRate) : 0;
int i;
// find a known baud rate in our list
setBaudIdx = -1;
for (i = 1; baudRates[i] > 0; i++) {
if (baudRates[i] == baud) {
setBaudIdx = i;
break;
}
}
// check the baud rate index
if (setBaudIdx < 1) {
if (baud == 0)
scheduleMsg(&btLogger, "The <baud> parameter is set to zero! The baud rate won't be set!");
else {
// unknown baud rate
scheduleMsg(&btLogger, "Wrong <baud> parameter '%s'! %s", baudRate, usage);
return;
}
} else {
// ok, add command!
}
// 2) check name
if (name == NULL || strlen(name) < 1 || strlen(name) > 20) {
scheduleMsg(&btLogger, "Wrong <name> parameter! Up to 20 characters expected! %s", usage);
return;
}
// 3) check pin code
int numDigits = 0;
// check the pincode
if (pinCode != NULL && strlen(pinCode) == 4) {
for (i = 0; i < 4; i++) {
if (pinCode[i] >= '0' && pinCode[i] <= '9') // digit
numDigits++;
}
}
if (numDigits != 4) {
scheduleMsg(&btLogger, "Wrong <pincode> parameter! 4 digits expected! %s", usage);
return;
}
// ok, add commands!
commands[numCommands++] = "AT"; // this command is added to test a connection
chsnprintf(cmdBaud, sizeof(cmdBaud), "AT+BAUD%c", '0' + setBaudIdx);
commands[numCommands++] = cmdBaud;
chsnprintf(cmdName, sizeof(cmdName), "AT+NAME%s", name);
commands[numCommands++] = cmdName;
chsnprintf(cmdPin, sizeof(cmdPin), "AT+PIN%s", pinCode);
commands[numCommands++] = cmdPin;
// create a thread to execute these commands later
btThread = chThdCreateStatic(btThreadStack, sizeof(btThreadStack), NORMALPRIO, (tfunc_t)btThreadEntryPoint, NULL);
btProcessIsStarted = true;
}
void bluetoothSoftwareDisconnectNotify() {
if (btProcessIsStarted) {
// start communication with the module
chThdResume(&btThreadRef, MSG_OK);
// wait the thread to finish
chThdWait(btThread);
}
}
void bluetoothCancel() {
if (!btProcessIsStarted) {
scheduleMsg(&btLogger, "The Bluetooth module init procedure was not started! Nothing to cancel!");
return;
}
if (btProcessIsRunning)
return;
// terminate thread
chThdTerminate(btThread);
btProcessIsStarted = false;
scheduleMsg(&btLogger, "The Bluetooth module init procedure is cancelled!");
}
#endif /* EFI_BLUETOOTH_SETUP */

View File

@ -0,0 +1,45 @@
/**
* @file tunerstudio.h
*
* @date Aug 26, 2013
* @author Andrey Belomutskiy, (c) 2012-2017
*/
#ifndef BLUETOOTH_H_
#define BLUETOOTH_H_
#include "main.h"
#include "tunerstudio_io.h"
// The Bluetooth setup procedure will wait 10 seconds for the user to disconnect the UART cable.
// This is required because the BT setup procedure reads a response from the module during the communication.
// Thus any bytes sent from the Console Software may interfere with the procedure.
#define BLUETOOTH_COMMAND_TIMEOUT MS2ST(10000)
// Supported Bluetooth module types
typedef enum {
BLUETOOTH_HC_06,
} bluetooth_module_e;
/**
* Start Bluetooth module initialization using UART connection:
* - wait for PC communication disconnect;
* - reconfigure the UART;
* - send AT-commands to the module;
* - restore connection to PC.
*/
void bluetoothStart(ts_channel_s *tsChannel, bluetooth_module_e moduleType, const char *baudRate, const char *name, const char *pinCode);
/**
* Cancel Bluetooth procedure
*/
void bluetoothCancel(void);
/**
* Called by runBinaryProtocolLoop() if a connection disconnect is detected.
* Bluetooth init code needs to make sure that there's no interference of the BT module and USB-UART (connected to PC)
*/
void bluetoothSoftwareDisconnectNotify();
#endif /* BLUETOOTH_H_ */

View File

@ -0,0 +1,38 @@
Bluetooth module setup procedure. User Manual.
To activate your Bluetooth module, you'll need:
1) Connect your PC to the rusEFI board using UART cable.
2) Run "rusEFI Console" software.
3) Turn on the board power and wait for the console connection.
4) Type the following command:
"bluetooth_hc06 <baud> <name> <pincode>"
Where:
- <baud> is the baud rate of the Bluetooth connection. Allowed values are: 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200.
Please set this to the baud rate currently used by your UART console.
- <name> is the name of your Bluetooth connection. It will be visible in the device list on your PC.
- <pincode> is 4-digit PIN-code needed to authorize the Bluetooth connection to your PC.
Example: "bluetooth_hc06 38400 rusefi 1234"
5) After entering the command the following text will appear:
*** Bluetooth module setup procedure ***
!Warning! Please make sure you're not currently using the BT module for communication (not paired)!
TO START THE PROCEDURE: PLEASE DISCONNECT YOUR PC COM-PORT FROM THE BOARD NOW!
After that please don't turn off the board power and wait for ~15 seconds to complete. Then reconnect to the board!
6) If you ignore this message and do nothing, the Bluetooth secup procedure will be cancelled in 10 seconds.
You can also use "bluetooth_cancel" command to cancel it.
7) If you disconnect the UART cable or close the software, then the procedure will begin.
8) It takes up to 15 seconds to complete. The Bluetooth LED may blink several times during the procedure - it's normal.
9) After that, you may restore the UART connection to your PC or start using Bluetooth module.
*** Developers Section ***
How it works, in two words:
- adds 2 new commands: "bluetooth_hc06(baud, name, pincode)" and "bluetooth_cancel";
- adds stopTsPort() to tunerstudio_io - needed to change the baud rate on fly;
- added bluetoothSoftwareDisconnectNotify() handler to runBinaryProtocolLoop() - to detect UART disconnects;
- added a thread with btThreadEntryPoint():
- It will wait up to 10 seconds for the user to disconnect the UART cable.
This is required because the BT setup procedure reads a response from the module during the communication - using the same UART.
Thus any bytes sent from the Console Software may interfere with the procedure.
- added bluetoothStart() which processes user input and creates a command list;
- added runCommands() where all the Bluetooth magic happens!