In case anyone is having difficulty using the Hands Free Profile (HFP) with the wt32, here’s a function that I wrote for Ardiuno. It works well – syncs to my cellphone, places calls and receives calls. I have some more refinements to do (e.g. debouncing the input from a keypad attached to the Ardino), but I thought I might as well post the code now.
It is organized as a state machine, which works well with Real-Time Programming. I use a blinkM indicate to the user what state its in (e.g. green = time to sync bluetooth with phone). It is called from within the loop() function.
void loop_bluetooth()
{
char serialOutput[100] = {0};
boolean serialReceived = false;
char serialInputReceived[100] = {0};
// Get input from the wt32 Bluetooth module
if (Serial.available() > 0)
{
serialInput[serialNextIndex] = Serial.read();
if (serialInput[serialNextIndex] == ‘\n’)
{
strcpy(serialInputReceived, serialInput);
serialNextIndex = 0;
}
else
{
serialNextIndex++;
}
}
// Next State Logic
//
// SETUP
// |
// |/
// V
// READY
// |
// |/
// V
// CONNECTED <-------------+
// | | |
// |/ |/ |
// V V |
// CALL RECEIVED DIALING |
// | | |
// |/ |/ |
// V V |
// ANSWER CALL DIAL NUMBER |
// | | |
// |/ |/ |
// V V |
// CALL IN PROGRESS |
// | |
// |/ |
// V |
// HANGING UP -------------+
//
switch(btState)
{
case STATE_SETUP:
if(setupComplete) btState = STATE_READY_TO_CONNECT;
break;
case STATE_READY_TO_CONNECT:
if (stringCompare(serialInputReceived, “HFP 0 READY”)) btState = STATE_CONNECTED;
break;
case STATE_CONNECTED:
if (stringCompare(serialInputReceived, “HFP 0 RING”)) btState = STATE_CALL_RECEIVED;
if (digitalRead(HOOK) == HIGH) btState = STATE_DIALING;
if (stringCompare(serialInputReceived, “NO CARRIER 0”)) btState = STATE_READY_TO_CONNECT;
break;
case STATE_CALL_RECEIVED:
if (digitalRead(HOOK) == HIGH) btState = STATE_ANSWER_CALL;
if (stringCompare(serialInputReceived, “NO CARRIER 0”)) btState = STATE_READY_TO_CONNECT;
break;
case STATE_ANSWER_CALL:
if (callAnswered) btState = STATE_CALL_IN_PROGRESS;
if (digitalRead(HOOK) == LOW) btState = STATE_HANGING_UP;
if (stringCompare(serialInputReceived, “NO CARRIER 0”)) btState = STATE_READY_TO_CONNECT;
break;
case STATE_DIALING:
if (readyToDial) btState = STATE_DIAL_NUMBER;
if (digitalRead(HOOK) == LOW) btState = STATE_HANGING_UP;
if (stringCompare(serialInputReceived, “NO CARRIER 0”)) btState = STATE_READY_TO_CONNECT;
break;
case STATE_DIAL_NUMBER:
if (numberDialed) btState = STATE_CALL_IN_PROGRESS;
if (digitalRead(HOOK) == LOW) btState = STATE_HANGING_UP;
if (stringCompare(serialInputReceived, “NO CARRIER 0”)) btState = STATE_READY_TO_CONNECT;
break;
case STATE_CALL_IN_PROGRESS:
if (digitalRead(HOOK) == LOW) btState = STATE_HANGING_UP;
if (stringCompare(serialInputReceived, “NO CARRIER 0”)) btState = STATE_READY_TO_CONNECT;
break;
case STATE_HANGING_UP:
if (hungUp) btState = STATE_CONNECTED;
if (stringCompare(serialInputReceived, “NO CARRIER 0”)) btState = STATE_READY_TO_CONNECT;
break;
default:
break;
}
strcpy (serialInputReceived, ‘\0’); // Only evaluate serialInputReceived once
// State Behavior Logic
switch(btState)
{
case STATE_SETUP:
Serial.print(“SET CONTROL ECHO 0\n”);
delay(500);
Serial.print(“SET CONTROL CONFIG 100\n”); //Enable SCO Links
delay(500);
Serial.print(“SET PROFILE HFP ON\n”); //Put iWRAP into HFP mode
delay(500);
Serial.print(“SET BT AUTH * 1234\n”); //Set the password
delay(500);
Serial.print(“SET BT CLASS 200428\n”); //Set device class
delay(500);
Serial.print(“SET BT NAME BT-PHONE\n”); //Set the bluetooth name
delay(500);
Serial.print(“SET CONTROL GAIN 8 7\n”);
//Serial.print(“VOLUME 9\n”);
delay(500);
Serial.print(“SET CONTROL MICBIAS 6 F\n”);
delay(500);
Serial.print(“RESET\n”);
delay(500);
setupComplete = true;
break;
case STATE_READY_TO_CONNECT:
// No action, wait
hungUp = false; // Reset flag
r=0;g=16;b=0;
break;
case STATE_CONNECTED:
// No action, wait
hungUp = false; // Reset flag
r=0;g=0;b=16;
break;
case STATE_CALL_RECEIVED:
// No action, wait
//r=32;g=32;b=32;
break;
case STATE_ANSWER_CALL:
Serial.print(“ANSWER\n”);
callAnswered = true;
//r=0;g=0;b=0;
break;
case STATE_DIALING:
// To move from this state, readyToDial = true; must be asserted (i.e. by keypa
if (keypadInput == ‘1’) {phoneThisNumber[phoneThisNumberIndex++] = ‘1’; BlinkM_setRGB( blinkm_addr, 0,0, 16 ); delay(400);}
if (keypadInput == ‘2’) {phoneThisNumber[phoneThisNumberIndex++] = ‘2’; BlinkM_setRGB( blinkm_addr, 0,0, 16 ); delay(400);}
if (keypadInput == ‘3’) {phoneThisNumber[phoneThisNumberIndex++] = ‘3’; BlinkM_setRGB( blinkm_addr, 0,0, 16 ); delay(400);}
if (keypadInput == ‘4’) {phoneThisNumber[phoneThisNumberIndex++] = ‘4’; BlinkM_setRGB( blinkm_addr, 0,0, 16 ); delay(400);}
if (keypadInput == ‘5’) {phoneThisNumber[phoneThisNumberIndex++] = ‘5’; BlinkM_setRGB( blinkm_addr, 0,0, 16 ); delay(400);}
if (keypadInput == ‘6’) {phoneThisNumber[phoneThisNumberIndex++] = ‘6’; BlinkM_setRGB( blinkm_addr, 0,0, 16 ); delay(400);}
if (keypadInput == ‘7’) {phoneThisNumber[phoneThisNumberIndex++] = ‘7’; BlinkM_setRGB( blinkm_addr, 0,0, 16 ); delay(400);}
if (keypadInput == ‘8’) {phoneThisNumber[phoneThisNumberIndex++] = ‘8’; BlinkM_setRGB( blinkm_addr, 0,0, 16 ); delay(400);}
if (keypadInput == ‘9’) {phoneThisNumber[phoneThisNumberIndex++] = ‘9’; BlinkM_setRGB( blinkm_addr, 0,0, 16 ); delay(400);}
if (keypadInput == ‘0’) {phoneThisNumber[phoneThisNumberIndex++] = ‘0’; BlinkM_setRGB( blinkm_addr, 0,0, 16 ); delay(400);}
if (keypadInput == ‘*’) {strcpy(phoneThisNumber, ‘\0’); phoneThisNumberIndex = 0; BlinkM_setRGB( blinkm_addr,16,0,0 ); delay(1000);} // Hit * to start over
if (keypadInput == ‘#’) readyToDial = true; // Hit # to dial
if (keypadInput == ‘N’);
if (keypadInput == ‘?’);
r=8;g=8;b=8;
break;
case STATE_DIAL_NUMBER:
Serial.print("\natd ");
for (int i=0;i<=phoneThisNumberIndex;i++) Serial.print(phoneThisNumber*);*
Serial.print(“\n”);
strcpy(phoneThisNumber, ‘\0’);
phoneThisNumberIndex = 0;
readyToDial = false; // Reset flag
numberDialed = true;
r=0;g=16;b=16;
break;
case STATE_CALL_IN_PROGRESS:
// No action, wait
numberDialed = false; // Reset flag
callAnswered = false; // Reset flag
r=0;g=8;b=8;
break;
case STATE_HANGING_UP:
Serial.print(“HANGUP\n”);
hungUp = true;
//r=0;g=0;b=0;
break;
default:
break;
}
}
Here’s my my stringCompare() function, which might be useful:
boolean stringCompare(char* string1, char *string2)
{
int stringIndex = 0;
for (int i =0; i<strlen(string2);i++)
if (string2 != ‘?’) // Add wildcard functionality
if (string1 != string2) return false;
return true;
}
Enjoy.