|
27 | 27 | #define DEBUG_PRINT(...) |
28 | 28 | #endif |
29 | 29 |
|
30 | | -/** |
31 | | - * Bluetooth power state. True means on (or on requested) False means off (or off requested). |
32 | | - */ |
33 | | -static bool power_on_requested; |
34 | | - |
35 | | -/** |
36 | | - * Bluetooth power enable busy state. True means that the operation is busy. |
37 | | - * |
38 | | - * Starts off in the reset state, so starts busy. |
39 | | - */ |
40 | | -static bool power_change_busy = true; |
41 | | - |
42 | | -pbio_error_t pbdrv_bluetooth_power_on(pbio_os_state_t *state, bool on) { |
43 | | - PBIO_OS_ASYNC_BEGIN(state); |
44 | | - |
45 | | - // Await ongoing state change if any. |
46 | | - PBIO_OS_AWAIT_WHILE(state, power_change_busy); |
47 | | - |
48 | | - // Already in requested state. |
49 | | - if (power_on_requested == on) { |
50 | | - return PBIO_SUCCESS; |
51 | | - } |
52 | | - |
53 | | - // Kick the Bluetooth process and await Bluetooth to become ready again. |
54 | | - power_change_busy = true; |
55 | | - power_on_requested = on; |
56 | | - pbio_os_request_poll(); |
57 | | - PBIO_OS_AWAIT_WHILE(state, power_change_busy); |
58 | | - |
59 | | - PBIO_OS_ASYNC_END(PBIO_SUCCESS); |
60 | | -} |
61 | | - |
62 | 30 | pbdrv_bluetooth_receive_handler_t pbdrv_bluetooth_receive_handler; |
63 | 31 |
|
64 | 32 | void pbdrv_bluetooth_set_receive_handler(pbdrv_bluetooth_receive_handler_t handler) { |
@@ -98,6 +66,7 @@ void pbdrv_bluetooth_init(void) { |
98 | 66 | // as soon as the previous one completes + 1 byte for ring buf pointer |
99 | 67 | static uint8_t stdout_buf[PBDRV_BLUETOOTH_MAX_CHAR_SIZE * 2 + 1]; |
100 | 68 | lwrb_init(&stdout_ring_buf, stdout_buf, PBIO_ARRAY_SIZE(stdout_buf)); |
| 69 | + pbio_busy_count_up(); |
101 | 70 |
|
102 | 71 | pbdrv_bluetooth_init_hci(); |
103 | 72 | } |
@@ -450,112 +419,98 @@ pbio_error_t pbdrv_bluetooth_process_thread(pbio_os_state_t *state, void *contex |
450 | 419 |
|
451 | 420 | PBIO_OS_ASYNC_BEGIN(state); |
452 | 421 |
|
453 | | - while (!shutting_down) { |
454 | | - |
455 | | - DEBUG_PRINT("Bluetooth disable requested.\n"); |
456 | | - |
457 | | - pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_NONE; |
458 | | - pbdrv_bluetooth_is_observing = false; |
459 | | - observe_restart_requested = false; |
| 422 | +init: |
460 | 423 |
|
461 | | - PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_controller_reset(&sub, &timer)); |
| 424 | + DEBUG_PRINT("Bluetooth reset.\n"); |
462 | 425 |
|
463 | | - DEBUG_PRINT("Bluetooth is now off.\n"); |
464 | | - power_change_busy = false; |
465 | | - pbio_os_request_poll(); |
| 426 | + PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_controller_reset(&sub, &timer)); |
466 | 427 |
|
467 | | - // Bluetooth is now disabled. Await system processes to ask for enable. |
468 | | - PBIO_OS_AWAIT_UNTIL(state, power_on_requested || shutting_down); |
469 | | - if (shutting_down) { |
470 | | - break; |
471 | | - } |
472 | | - DEBUG_PRINT("Bluetooth enable requested.\n"); |
| 428 | + DEBUG_PRINT("Bluetooth enable.\n"); |
473 | 429 |
|
474 | | - PBIO_OS_AWAIT(state, &sub, err = pbdrv_bluetooth_controller_initialize(&sub, &timer)); |
475 | | - if (err != PBIO_SUCCESS) { |
476 | | - DEBUG_PRINT("Initialization failed. Reset and retry.\n"); |
477 | | - continue; |
478 | | - } |
| 430 | + PBIO_OS_AWAIT(state, &sub, err = pbdrv_bluetooth_controller_initialize(&sub, &timer)); |
| 431 | + if (err != PBIO_SUCCESS) { |
| 432 | + DEBUG_PRINT("Initialization failed. Reset and retry.\n"); |
| 433 | + goto init; |
| 434 | + } |
479 | 435 |
|
480 | | - DEBUG_PRINT("Bluetooth is now on and initialized.\n"); |
481 | | - power_change_busy = false; |
482 | | - pbio_os_request_poll(); |
| 436 | + DEBUG_PRINT("Bluetooth is now on and initialized.\n"); |
483 | 437 |
|
484 | | - pbio_os_timer_set(&status_timer, PBDRV_BLUETOOTH_STATUS_UPDATE_INTERVAL); |
| 438 | + pbio_busy_count_down(); |
485 | 439 |
|
486 | | - // Service scheduled tasks as long as Bluetooth is enabled. |
487 | | - while (power_on_requested && !shutting_down) { |
| 440 | + pbio_os_timer_set(&status_timer, PBDRV_BLUETOOTH_STATUS_UPDATE_INTERVAL); |
488 | 441 |
|
489 | | - // In principle, this wait is only needed if there is nothing to do. |
490 | | - // In practice, leaving it here helps rather than hurts since it |
491 | | - // allows short stdout messages to be queued rather than sent separately. |
492 | | - PBIO_OS_AWAIT_MS(state, &timer, 1); |
| 442 | + // Service scheduled tasks as long as Bluetooth is enabled. |
| 443 | + while (!shutting_down) { |
493 | 444 |
|
494 | | - // Handle pending status update, if any. |
495 | | - if (can_send && (status_data_pending || pbio_os_timer_is_expired(&status_timer))) { |
| 445 | + // In principle, this wait is only needed if there is nothing to do. |
| 446 | + // In practice, leaving it here helps rather than hurts since it |
| 447 | + // allows short stdout messages to be queued rather than sent separately. |
| 448 | + PBIO_OS_AWAIT_MS(state, &timer, 1); |
496 | 449 |
|
497 | | - // When a status is pending, cache it here while we write it out, |
498 | | - // so a new status can be set in the mean time without losing it. |
499 | | - static uint8_t status_buf[PBIO_PYBRICKS_EVENT_STATUS_REPORT_SIZE]; |
500 | | - memcpy(status_buf, status_data, PBIO_PYBRICKS_EVENT_STATUS_REPORT_SIZE); |
501 | | - status_data_pending = false; |
| 450 | + // Handle pending status update, if any. |
| 451 | + if (can_send && (status_data_pending || pbio_os_timer_is_expired(&status_timer))) { |
502 | 452 |
|
503 | | - PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_send_pybricks_value_notification(&sub, status_buf, sizeof(status_buf))); |
| 453 | + // When a status is pending, cache it here while we write it out, |
| 454 | + // so a new status can be set in the mean time without losing it. |
| 455 | + static uint8_t status_buf[PBIO_PYBRICKS_EVENT_STATUS_REPORT_SIZE]; |
| 456 | + memcpy(status_buf, status_data, PBIO_PYBRICKS_EVENT_STATUS_REPORT_SIZE); |
| 457 | + status_data_pending = false; |
504 | 458 |
|
505 | | - pbio_os_timer_set(&status_timer, status_timer.duration); |
506 | | - } |
| 459 | + PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_send_pybricks_value_notification(&sub, status_buf, sizeof(status_buf))); |
507 | 460 |
|
508 | | - // Handle pending stdout, if any. |
509 | | - if (can_send && lwrb_get_full(&stdout_ring_buf) != 0) { |
510 | | - stdout_send_busy = true; |
| 461 | + pbio_os_timer_set(&status_timer, status_timer.duration); |
| 462 | + } |
511 | 463 |
|
512 | | - static uint8_t stdout_buf[PBDRV_BLUETOOTH_MAX_CHAR_SIZE] = { PBIO_PYBRICKS_EVENT_WRITE_STDOUT }; |
513 | | - static uint16_t stdout_len; |
| 464 | + // Handle pending stdout, if any. |
| 465 | + if (can_send && lwrb_get_full(&stdout_ring_buf) != 0) { |
| 466 | + stdout_send_busy = true; |
514 | 467 |
|
515 | | - stdout_len = lwrb_read(&stdout_ring_buf, &stdout_buf[1], PBDRV_BLUETOOTH_MAX_CHAR_SIZE - 1) + 1; |
516 | | - PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_send_pybricks_value_notification(&sub, stdout_buf, stdout_len)); |
| 468 | + static uint8_t stdout_buf[PBDRV_BLUETOOTH_MAX_CHAR_SIZE] = { PBIO_PYBRICKS_EVENT_WRITE_STDOUT }; |
| 469 | + static uint16_t stdout_len; |
517 | 470 |
|
518 | | - stdout_send_busy = false; |
519 | | - } |
| 471 | + stdout_len = lwrb_read(&stdout_ring_buf, &stdout_buf[1], PBDRV_BLUETOOTH_MAX_CHAR_SIZE - 1) + 1; |
| 472 | + PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_send_pybricks_value_notification(&sub, stdout_buf, stdout_len)); |
520 | 473 |
|
521 | | - // Handle pending user value notification, if any. |
522 | | - if (can_send && user_notification_size) { |
| 474 | + stdout_send_busy = false; |
| 475 | + } |
523 | 476 |
|
524 | | - PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_send_pybricks_value_notification(&sub, |
525 | | - user_notification_send_buf, |
526 | | - user_notification_size)); |
| 477 | + // Handle pending user value notification, if any. |
| 478 | + if (can_send && user_notification_size) { |
527 | 479 |
|
528 | | - user_notification_size = 0; |
529 | | - } |
| 480 | + PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_send_pybricks_value_notification(&sub, |
| 481 | + user_notification_send_buf, |
| 482 | + user_notification_size)); |
530 | 483 |
|
531 | | - // Handle pending advertising/scan enable/disable task, if any. |
532 | | - if (advertising_or_scan_func) { |
533 | | - PBIO_OS_AWAIT(state, &sub, advertising_or_scan_err = advertising_or_scan_func(&sub, NULL)); |
534 | | - advertising_or_scan_func = NULL; |
535 | | - } |
536 | | - |
537 | | - // Handle pending peripheral task, if any. |
538 | | - if (peri->func) { |
| 484 | + user_notification_size = 0; |
| 485 | + } |
539 | 486 |
|
540 | | - // If currently observing, stop if we need to scan for a peripheral. |
541 | | - if (pbdrv_bluetooth_is_observing && peri->func == pbdrv_bluetooth_peripheral_scan_and_connect_func) { |
542 | | - PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_stop_observing_func(&sub, NULL)); |
543 | | - observe_restart_requested = true; |
544 | | - } |
| 487 | + // Handle pending advertising/scan enable/disable task, if any. |
| 488 | + if (advertising_or_scan_func) { |
| 489 | + PBIO_OS_AWAIT(state, &sub, advertising_or_scan_err = advertising_or_scan_func(&sub, NULL)); |
| 490 | + advertising_or_scan_func = NULL; |
| 491 | + } |
545 | 492 |
|
546 | | - PBIO_OS_AWAIT(state, &sub, peri->err = peri->func(&sub, peri)); |
547 | | - peri->func = NULL; |
548 | | - peri->cancel = false; |
549 | | - } |
| 493 | + // Handle pending peripheral task, if any. |
| 494 | + if (peri->func) { |
550 | 495 |
|
551 | | - // Restart if we stopped it temporarily to scan for a peripheral or |
552 | | - // when externaly requested. |
553 | | - if (observe_restart_requested) { |
554 | | - DEBUG_PRINT("Restart observe.\n"); |
| 496 | + // If currently observing, stop if we need to scan for a peripheral. |
| 497 | + if (pbdrv_bluetooth_is_observing && peri->func == pbdrv_bluetooth_peripheral_scan_and_connect_func) { |
555 | 498 | PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_stop_observing_func(&sub, NULL)); |
556 | | - PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_start_observing_func(&sub, NULL)); |
557 | | - observe_restart_requested = false; |
| 499 | + observe_restart_requested = true; |
558 | 500 | } |
| 501 | + |
| 502 | + PBIO_OS_AWAIT(state, &sub, peri->err = peri->func(&sub, peri)); |
| 503 | + peri->func = NULL; |
| 504 | + peri->cancel = false; |
| 505 | + } |
| 506 | + |
| 507 | + // Restart if we stopped it temporarily to scan for a peripheral or |
| 508 | + // when externaly requested. |
| 509 | + if (observe_restart_requested) { |
| 510 | + DEBUG_PRINT("Restart observe.\n"); |
| 511 | + PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_stop_observing_func(&sub, NULL)); |
| 512 | + PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_start_observing_func(&sub, NULL)); |
| 513 | + observe_restart_requested = false; |
559 | 514 | } |
560 | 515 | } |
561 | 516 |
|
|
0 commit comments