19 #define DEBUG // Uncomment to print data for debugging
23 const uint8_t OUTPUT_REPORT_BUFFER[]
PROGMEM = {
24 0x00, 0x00, 0x00, 0x00, 0x00,
25 0x00, 0x00, 0x00, 0x00, 0x00,
26 0xff, 0x27, 0x10, 0x00, 0x32,
27 0xff, 0x27, 0x10, 0x00, 0x32,
28 0xff, 0x27, 0x10, 0x00, 0x32,
29 0xff, 0x27, 0x10, 0x00, 0x32,
30 0x00, 0x00, 0x00, 0x00, 0x00,
31 0x00, 0x00, 0x00, 0x00, 0x00,
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
35 PS3BT::PS3BT(
BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0):
52 HIDMoveBuffer[0] = 0xA2;
53 HIDMoveBuffer[1] = 0x02;
56 control_dcid[0] = 0x40;
57 control_dcid[1] = 0x00;
58 interrupt_dcid[0] = 0x41;
59 interrupt_dcid[1] = 0x00;
64 return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b]));
67 uint32_t button = pgm_read_dword(&BUTTONS[(uint8_t)b]);
68 bool click = (ButtonClickState & button);
69 ButtonClickState &= ~button;
73 if (l2capinbuf == NULL)
75 return (uint8_t)(l2capinbuf[pgm_read_byte(&ANALOGBUTTONS[(uint8_t)a])]);
78 if (l2capinbuf == NULL)
80 return (uint8_t)(l2capinbuf[(uint8_t)a+15]);
83 if (l2capinbuf == NULL)
86 if (a ==
aX || a ==
aY || a ==
aZ || a ==
gZ)
87 return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]);
92 return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1]));
94 return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4));
96 return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8));
107 const double zeroG = 511.5;
113 const uint16_t zeroG = 0x8000;
123 double angle = (atan2(accYval,accZval)+PI)*RAD_TO_DEG;
126 double angle = (atan2(accXval,accZval)+PI)*RAD_TO_DEG;
137 return (
double)value/3.2;
143 return (
double)value/442.0;
150 return (
double)value/11.6;
152 return (
double)value/11.2;
154 return (
double)value/9.6;
162 String output = String(input/100);
166 output += String(input%100);
172 if (l2capinbuf == NULL)
174 if (l2capinbuf[(uint16_t)c >> 8] == ((uint8_t)c & 0xff))
180 char statusOutput[100];
182 strcpy(statusOutput,
"ConnectionStatus: ");
186 else strcat(statusOutput,
"Error");
189 strcat(statusOutput,
" - PowerRating: ");
197 else strcat(statusOutput,
"Error");
199 strcat(statusOutput,
" - WirelessStatus: ");
202 else if (
getStatus(
Cable)) strcat(statusOutput,
"Cable - Rumble is off");
205 else strcat(statusOutput,
"Error");
211 char statusOutput[50];
213 strcpy(statusOutput,
"PowerRating: ");
222 else strcat(statusOutput,
"Error");
231 activeConnection =
false;
232 l2cap_event_flag = 0;
237 HIDBuffer[i + 2] = pgm_read_byte(&OUTPUT_REPORT_BUFFER[i]);
250 if((ACLData[12] | (ACLData[13] << 8)) ==
HID_CTRL_PSM) {
252 activeConnection =
true;
255 for(uint8_t i = 0; i < 30; i++)
259 Notify(PSTR(
"\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "));
261 Notify(PSTR(
"\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"));
267 if (((ACLData[0] | (ACLData[1] << 8)) == (hci_handle | 0x2000))) {
269 l2capinbuf[i] = ACLData[i];
270 if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) {
273 Notify(PSTR(
"\r\nL2CAP Command Rejected - Reason: "));
274 PrintHex<uint8_t>(l2capinbuf[13]);
276 PrintHex<uint8_t>(l2capinbuf[12]);
277 Serial.print(
" Data: ");
278 PrintHex<uint8_t>(l2capinbuf[17]);
280 PrintHex<uint8_t>(l2capinbuf[16]);
282 PrintHex<uint8_t>(l2capinbuf[15]);
284 PrintHex<uint8_t>(l2capinbuf[14]);
289 Notify(PSTR(
"\r\nL2CAP Connection Request - PSM: "));
290 PrintHex<uint8_t>(l2capinbuf[13]);
292 PrintHex<uint8_t>(l2capinbuf[12]);
294 PrintHex<uint8_t>(l2capinbuf[15]);
296 PrintHex<uint8_t>(l2capinbuf[14]);
297 Notify(PSTR(
" Identifier: "));
298 PrintHex<uint8_t>(l2capinbuf[9]);
300 if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) ==
HID_CTRL_PSM) {
301 identifier = l2capinbuf[9];
302 control_scid[0] = l2capinbuf[14];
303 control_scid[1] = l2capinbuf[15];
306 else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) ==
HID_INTR_PSM) {
307 identifier = l2capinbuf[9];
308 interrupt_scid[0] = l2capinbuf[14];
309 interrupt_scid[1] = l2capinbuf[15];
314 if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) {
315 if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
319 else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
326 if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
328 identifier = l2capinbuf[9];
331 else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
333 identifier = l2capinbuf[9];
338 if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
340 Notify(PSTR(
"\r\nDisconnect Request: Control Channel"));
342 identifier = l2capinbuf[9];
346 else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
348 Notify(PSTR(
"\r\nDisconnect Request: Interrupt Channel"));
350 identifier = l2capinbuf[9];
356 if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
358 identifier = l2capinbuf[9];
361 else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
363 identifier = l2capinbuf[9];
369 Notify(PSTR(
"\r\nL2CAP Unknown Signaling Command: "));
370 PrintHex<uint8_t>(l2capinbuf[8]);
373 }
else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) {
377 if(l2capinbuf[8] == 0xA1) {
379 ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16));
381 ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16));
386 if(ButtonState != OldButtonState) {
387 ButtonClickState = ButtonState & ~OldButtonState;
388 OldButtonState = ButtonState;
391 #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
392 for(uint8_t i = 10; i < 58;i++) {
393 PrintHex<uint8_t>(l2capinbuf[i]);
404 void PS3BT::L2CAP_task() {
405 switch (l2cap_state) {
409 Notify(PSTR(
"\r\nHID Control Incoming Connection Request"));
423 Notify(PSTR(
"\r\nHID Control Configuration Request"));
433 Notify(PSTR(
"\r\nHID Control Successfully Configured"));
441 Notify(PSTR(
"\r\nHID Interrupt Incoming Connection Request"));
456 Notify(PSTR(
"\r\nHID Interrupt Configuration Request"));
465 Notify(PSTR(
"\r\nHID Interrupt Successfully Configured"));
467 if(remote_name[0] ==
'M') {
485 Notify(PSTR(
"\r\nDisconnected Interrupt Channel"));
496 Notify(PSTR(
"\r\nDisconnected Control Channel"));
500 l2cap_event_flag = 0;
507 switch (l2cap_state) {
509 if(millis() - timer > 1000) {
516 for (uint8_t i = 15; i < 19; i++)
517 l2capinbuf[i] = 0x7F;
524 if(millis() - timer > 1000) {
525 if (remote_name[0] ==
'P') {
528 Notify(PSTR(
"\r\nDualshock 3 Controller Enabled\r\n"));
531 }
else if (remote_name[0] ==
'N') {
534 Notify(PSTR(
"\r\nNavigation Controller Enabled\r\n"));
537 }
else if(remote_name[0] ==
'M') {
539 timerBulbRumble = millis();
541 Notify(PSTR(
"\r\nMotion Controller Enabled\r\n"));
551 if (millis() - timerBulbRumble > 4000) {
553 timerBulbRumble = millis();
565 void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) {
566 if (millis() - timerHID <= 250)
567 delay((uint32_t)(250 - (millis() - timerHID)));
568 pBtd->
L2CAP_Command(hci_handle,data,nbytes,control_scid[0],control_scid[1]);
573 HIDBuffer[i + 2] = pgm_read_byte(&OUTPUT_REPORT_BUFFER[i]);
592 if ((mode & 0x30) > 0) {
607 HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1));
611 HIDBuffer[11] |= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1);
615 HIDBuffer[11] ^= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1);
618 void PS3BT::enable_sixaxis() {
627 HID_Command(cmd_buf, 6);
631 void PS3BT::HIDMove_Command(uint8_t* data,uint8_t nbytes) {
632 if (millis() - timerHID <= 250)
633 delay((uint32_t)(250 - (millis() - timerHID)));
634 pBtd->
L2CAP_Command(hci_handle,data,nbytes,interrupt_scid[0],interrupt_scid[1]);
639 HIDMoveBuffer[3] = r;
640 HIDMoveBuffer[4] = g;
641 HIDMoveBuffer[5] = b;
646 moveSetBulb((uint8_t)(color >> 16),(uint8_t)(color >> 8),(uint8_t)(color));
650 if(rumble < 64 && rumble != 0)
651 Notify(PSTR(
"\r\nThe rumble value has to at least 64, or approximately 25%"));
654 HIDMoveBuffer[7] = rumble;