From ae30a1e5aa198bdeee7dce04194b027ff4e3d65a Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Sat, 14 Sep 2019 12:40:24 -0700 Subject: [PATCH 01/38] Refine _bleio This PR refines the _bleio API. It was originally motivated by the addition of a new CircuitPython service that enables reading and modifying files on the device. Moving the BLE lifecycle outside of the VM motivated a number of changes to remove heap allocations in some APIs. It also motivated unifying connection initiation to the Adapter class rather than the Central and Peripheral classes which have been removed. Adapter now handles the GAP portion of BLE including advertising, which has moved but is largely unchanged, and scanning, which has been enhanced to return an iterator of filtered results. Once a connection is created (either by us (aka Central) or a remote device (aka Peripheral)) it is represented by a new Connection class. This class knows the current connection state and can discover and instantiate remote Services along with their Characteristics and Descriptors. Relates to #586 --- lib/utils/interrupt_char.c | 2 +- main.c | 13 + ports/nrf/background.c | 7 + ports/nrf/bluetooth/ble_drv.c | 28 +- ports/nrf/bluetooth/ble_drv.h | 7 +- ports/nrf/boards/adafruit_nrf52840_s140_v6.ld | 9 +- ports/nrf/common-hal/_bleio/Adapter.c | 539 +++++++++++++-- ports/nrf/common-hal/_bleio/Adapter.h | 20 +- ports/nrf/common-hal/_bleio/Central.c | 145 ---- ports/nrf/common-hal/_bleio/Characteristic.c | 120 ++-- ports/nrf/common-hal/_bleio/Characteristic.h | 5 +- .../common-hal/_bleio/CharacteristicBuffer.c | 12 +- ports/nrf/common-hal/_bleio/Connection.c | 629 ++++++++++++++++++ .../_bleio/{Peripheral.h => Connection.h} | 38 +- ports/nrf/common-hal/_bleio/Descriptor.c | 58 +- ports/nrf/common-hal/_bleio/Descriptor.h | 9 +- ports/nrf/common-hal/_bleio/Peripheral.c | 361 ---------- ports/nrf/common-hal/_bleio/Scanner.c | 105 --- ports/nrf/common-hal/_bleio/Service.c | 48 +- ports/nrf/common-hal/_bleio/Service.h | 12 +- ports/nrf/common-hal/_bleio/UUID.c | 23 +- ports/nrf/common-hal/_bleio/__init__.c | 495 +++----------- ports/nrf/common-hal/_bleio/__init__.h | 5 + py/circuitpy_defns.mk | 5 +- py/ringbuf.h | 7 + py/vm.c | 2 +- shared-bindings/_bleio/Adapter.c | 300 ++++++++- shared-bindings/_bleio/Adapter.h | 28 +- shared-bindings/_bleio/Address.c | 30 +- shared-bindings/_bleio/Central.c | 207 ------ shared-bindings/_bleio/Central.h | 43 -- shared-bindings/_bleio/Characteristic.c | 33 +- shared-bindings/_bleio/Characteristic.h | 6 +- shared-bindings/_bleio/Connection.c | 171 +++++ .../_bleio/{Scanner.h => Connection.h} | 19 +- shared-bindings/_bleio/Descriptor.c | 9 +- shared-bindings/_bleio/Descriptor.h | 2 +- shared-bindings/_bleio/Peripheral.c | 325 --------- shared-bindings/_bleio/Peripheral.h | 48 -- shared-bindings/_bleio/ScanEntry.c | 74 ++- shared-bindings/_bleio/ScanEntry.h | 3 + shared-bindings/_bleio/ScanResults.c | 72 ++ .../_bleio/ScanResults.h | 17 +- shared-bindings/_bleio/Scanner.c | 129 ---- shared-bindings/_bleio/Service.c | 74 +-- shared-bindings/_bleio/Service.h | 14 +- shared-bindings/_bleio/UUID.c | 51 +- shared-bindings/_bleio/UUID.h | 5 +- shared-bindings/_bleio/__init__.c | 19 +- shared-bindings/_bleio/__init__.h | 18 +- shared-module/_bleio/ScanEntry.c | 43 +- shared-module/_bleio/ScanEntry.h | 7 +- shared-module/_bleio/ScanResults.c | 138 ++++ shared-module/_bleio/ScanResults.h | 64 ++ supervisor/shared/autoreload.c | 8 + supervisor/shared/autoreload.h | 2 + supervisor/shared/bluetooth.c | 341 ++++++++++ .../shared/bluetooth.h | 24 +- supervisor/shared/safe_mode.h | 3 +- supervisor/supervisor.mk | 5 + 60 files changed, 2887 insertions(+), 2149 deletions(-) delete mode 100644 ports/nrf/common-hal/_bleio/Central.c create mode 100644 ports/nrf/common-hal/_bleio/Connection.c rename ports/nrf/common-hal/_bleio/{Peripheral.h => Connection.h} (67%) delete mode 100644 ports/nrf/common-hal/_bleio/Peripheral.c delete mode 100644 ports/nrf/common-hal/_bleio/Scanner.c delete mode 100644 shared-bindings/_bleio/Central.c delete mode 100644 shared-bindings/_bleio/Central.h create mode 100644 shared-bindings/_bleio/Connection.c rename shared-bindings/_bleio/{Scanner.h => Connection.h} (66%) delete mode 100644 shared-bindings/_bleio/Peripheral.c delete mode 100644 shared-bindings/_bleio/Peripheral.h create mode 100644 shared-bindings/_bleio/ScanResults.c rename ports/nrf/common-hal/_bleio/Scanner.h => shared-bindings/_bleio/ScanResults.h (76%) delete mode 100644 shared-bindings/_bleio/Scanner.c create mode 100644 shared-module/_bleio/ScanResults.c create mode 100644 shared-module/_bleio/ScanResults.h create mode 100644 supervisor/shared/bluetooth.c rename ports/nrf/common-hal/_bleio/Central.h => supervisor/shared/bluetooth.h (66%) diff --git a/lib/utils/interrupt_char.c b/lib/utils/interrupt_char.c index 91ee5c80ef..da7f702544 100644 --- a/lib/utils/interrupt_char.c +++ b/lib/utils/interrupt_char.c @@ -49,7 +49,7 @@ void mp_keyboard_interrupt(void) { // Check to see if we've been CTRL-C'ed by autoreload or the user. bool mp_hal_is_interrupted(void) { - return MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); + return MP_STATE_VM(mp_pending_exception) != NULL; } #endif diff --git a/main.c b/main.c index 8715672ea9..a6c7c05816 100755 --- a/main.c +++ b/main.c @@ -69,6 +69,11 @@ #include "shared-module/board/__init__.h" #endif +#if CIRCUITPY_BLEIO +#include "shared-bindings/_bleio/__init__.h" +#include "supervisor/shared/bluetooth.h" +#endif + void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); if (lex == NULL) { @@ -439,6 +444,10 @@ int __attribute__((used)) main(void) { // Start serial and HID after giving boot.py a chance to tweak behavior. serial_init(); + #if CIRCUITPY_BLEIO + supervisor_start_bluetooth(); + #endif + // Boot script is finished, so now go into REPL/main mode. int exit_code = PYEXEC_FORCED_EXIT; bool skip_repl = true; @@ -475,6 +484,10 @@ void gc_collect(void) { displayio_gc_collect(); #endif + #if CIRCUITPY_BLEIO + common_hal_bleio_gc_collect(); + #endif + // This naively collects all object references from an approximate stack // range. gc_collect_root((void**)sp, ((uint32_t)port_stack_get_top() - sp) / sizeof(uint32_t)); diff --git a/ports/nrf/background.c b/ports/nrf/background.c index 305f607c5c..629967b3d0 100644 --- a/ports/nrf/background.c +++ b/ports/nrf/background.c @@ -41,6 +41,10 @@ #include "common-hal/audiopwmio/PWMAudioOut.h" #endif +#if CIRCUITPY_BLEIO +#include "supervisor/shared/bluetooth.h" +#endif + static bool running_background_tasks = false; void background_tasks_reset(void) { @@ -62,6 +66,9 @@ void run_background_tasks(void) { i2s_background(); #endif +#if CIRCUITPY_BLEIO + supervisor_bluetooth_background(); +#endif #if CIRCUITPY_DISPLAYIO displayio_background(); diff --git a/ports/nrf/bluetooth/ble_drv.c b/ports/nrf/bluetooth/ble_drv.c index 6b17e7af29..16475e4b3b 100644 --- a/ports/nrf/bluetooth/ble_drv.c +++ b/ports/nrf/bluetooth/ble_drv.c @@ -38,6 +38,8 @@ #include "py/misc.h" #include "py/mpstate.h" +#include "supervisor/shared/bluetooth.h" + nrf_nvic_state_t nrf_nvic_state = { 0 }; // Flag indicating progress of internal flash operation. @@ -52,6 +54,14 @@ void ble_drv_reset() { sd_flash_operation_status = SD_FLASH_OPERATION_DONE; } +void ble_drv_add_event_handler_entry(ble_drv_evt_handler_entry_t* entry, ble_drv_evt_handler_t func, void *param) { + entry->next = MP_STATE_VM(ble_drv_evt_handler_entries); + entry->param = param; + entry->func = func; + + MP_STATE_VM(ble_drv_evt_handler_entries) = entry; +} + void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param) { ble_drv_evt_handler_entry_t *it = MP_STATE_VM(ble_drv_evt_handler_entries); while (it != NULL) { @@ -64,11 +74,7 @@ void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param) { // Add a new handler to the front of the list ble_drv_evt_handler_entry_t *handler = m_new_ll(ble_drv_evt_handler_entry_t, 1); - handler->next = MP_STATE_VM(ble_drv_evt_handler_entries); - handler->param = param; - handler->func = func; - - MP_STATE_VM(ble_drv_evt_handler_entries) = handler; + ble_drv_add_event_handler_entry(handler, func, param); } void ble_drv_remove_event_handler(ble_drv_evt_handler_t func, void *param) { @@ -127,10 +133,20 @@ void SD_EVT_IRQHandler(void) { break; } + ble_evt_t* event = (ble_evt_t *)m_ble_evt_buf; + + if (supervisor_bluetooth_hook(event)) { + continue; + } + ble_drv_evt_handler_entry_t *it = MP_STATE_VM(ble_drv_evt_handler_entries); + bool done = false; while (it != NULL) { - it->func((ble_evt_t *)m_ble_evt_buf, it->param); + done = it->func(event, it->param) || done; it = it->next; } + if (!done) { + //mp_printf(&mp_plat_print, "Unhandled ble event: 0x%04x\n", event->header.evt_id); + } } } diff --git a/ports/nrf/bluetooth/ble_drv.h b/ports/nrf/bluetooth/ble_drv.h index a066f588fa..7716cab8be 100644 --- a/ports/nrf/bluetooth/ble_drv.h +++ b/ports/nrf/bluetooth/ble_drv.h @@ -29,6 +29,8 @@ #ifndef MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_DRV_H #define MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_DRV_H +#include + #include "ble.h" #define MAX_TX_IN_PROGRESS 10 @@ -48,7 +50,7 @@ #define UNIT_1_25_MS (1250) #define UNIT_10_MS (10000) -typedef void (*ble_drv_evt_handler_t)(ble_evt_t*, void*); +typedef bool (*ble_drv_evt_handler_t)(ble_evt_t*, void*); typedef enum { SD_FLASH_OPERATION_DONE, @@ -69,4 +71,7 @@ void ble_drv_reset(void); void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param); void ble_drv_remove_event_handler(ble_drv_evt_handler_t func, void *param); +// Allow for user provided entries to prevent allocations outside the VM. +void ble_drv_add_event_handler_entry(ble_drv_evt_handler_entry_t* entry, ble_drv_evt_handler_t func, void *param); + #endif // MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_DRV_H diff --git a/ports/nrf/boards/adafruit_nrf52840_s140_v6.ld b/ports/nrf/boards/adafruit_nrf52840_s140_v6.ld index 2587a19e34..756060f960 100644 --- a/ports/nrf/boards/adafruit_nrf52840_s140_v6.ld +++ b/ports/nrf/boards/adafruit_nrf52840_s140_v6.ld @@ -16,6 +16,7 @@ 0x00000000..0x00000FFF (4KB) Master Boot Record */ + /* Specify the memory areas (S140 6.x.x) */ MEMORY { @@ -26,7 +27,10 @@ MEMORY FLASH_FATFS (r) : ORIGIN = 0x000AD000, LENGTH = 0x040000 /* 0x2000000 - RAM:ORIGIN is reserved for Softdevice */ - RAM (xrw) : ORIGIN = 0x20004000, LENGTH = 0x20040000 - 0x20004000 + /* SoftDevice 6.1.0 takes 0x1628 bytes (5.54 kb) minimum. */ + /* To measure the minimum required amount of memory for given configuration, set this number + high enough to work and then check the mutation of the value done by sd_ble_enable. */ + RAM (xrw) : ORIGIN = 0x20000000 + 16K, LENGTH = 256K - 16K } /* produce a link error if there is not this amount of RAM for these sections */ @@ -38,7 +42,8 @@ _minimum_heap_size = 0; /*_stack_end = ORIGIN(RAM) + LENGTH(RAM);*/ _estack = ORIGIN(RAM) + LENGTH(RAM); -/* RAM extents for the garbage collector */ +/* RAM extents for the garbage collector and soft device init */ +_ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_end = 0x20020000; /* tunable */ diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index a8e1f19059..41189a86df 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -26,6 +26,7 @@ * THE SOFTWARE. */ +#include #include #include @@ -34,11 +35,18 @@ #include "nrfx_power.h" #include "nrf_nvic.h" #include "nrf_sdm.h" +#include "tick.h" +#include "py/gc.h" #include "py/objstr.h" #include "py/runtime.h" +#include "supervisor/shared/safe_mode.h" #include "supervisor/usb.h" +#include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Adapter.h" #include "shared-bindings/_bleio/Address.h" +#include "shared-bindings/_bleio/Connection.h" +#include "shared-bindings/_bleio/ScanEntry.h" +#include "shared-bindings/time/__init__.h" #define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) #define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) @@ -46,10 +54,13 @@ #define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) STATIC void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) { - mp_raise_msg_varg(&mp_type_AssertionError, - translate("Soft device assert, id: 0x%08lX, pc: 0x%08lX"), id, pc); + reset_into_safe_mode(NORDIC_SOFT_DEVICE_ASSERT); } +bleio_connection_internal_t connections[BLEIO_TOTAL_CONNECTION_COUNT]; + +// Linker script provided ram start. +extern uint32_t _ram_start; STATIC uint32_t ble_stack_enable(void) { nrf_clock_lf_cfg_t clock_config = { #if BOARD_HAS_32KHZ_XTAL @@ -78,34 +89,56 @@ STATIC uint32_t ble_stack_enable(void) { // Start with no event handlers, etc. ble_drv_reset(); - uint32_t app_ram_start; - app_ram_start = 0x20004000; + // Set everything up to have one persistent code editing connection and one user managed + // connection. In the future we could move .data and .bss to the other side of the stack and + // dynamically adjust for different memory requirements of the SD based on boot.py + // configuration. + uint32_t app_ram_start = (uint32_t) &_ram_start; ble_cfg_t ble_conf; ble_conf.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_TAG_CUSTOM; - ble_conf.conn_cfg.params.gap_conn_cfg.conn_count = BLE_GAP_CONN_COUNT_DEFAULT; + ble_conf.conn_cfg.params.gap_conn_cfg.conn_count = BLEIO_TOTAL_CONNECTION_COUNT; + // Event length here can influence throughput so perhaps make multiple connection profiles + // available. ble_conf.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_DEFAULT; err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_conf, app_ram_start); - if (err_code != NRF_SUCCESS) + if (err_code != NRF_SUCCESS) { return err_code; + } memset(&ble_conf, 0, sizeof(ble_conf)); - ble_conf.gap_cfg.role_count_cfg.periph_role_count = 1; + ble_conf.gap_cfg.role_count_cfg.adv_set_count = 1; + ble_conf.gap_cfg.role_count_cfg.periph_role_count = 2; ble_conf.gap_cfg.role_count_cfg.central_role_count = 1; err_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_conf, app_ram_start); - if (err_code != NRF_SUCCESS) + if (err_code != NRF_SUCCESS) { return err_code; + } memset(&ble_conf, 0, sizeof(ble_conf)); ble_conf.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_TAG_CUSTOM; ble_conf.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = MAX_TX_IN_PROGRESS; err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_conf, app_ram_start); - if (err_code != NRF_SUCCESS) + if (err_code != NRF_SUCCESS) { return err_code; + } - err_code = sd_ble_enable(&app_ram_start); - if (err_code != NRF_SUCCESS) + // Double the GATT Server attribute size to accomodate both the CircuitPython built-in service + // and anything the user does. + memset(&ble_conf, 0, sizeof(ble_conf)); + ble_conf.gatts_cfg.attr_tab_size.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT * 3; + err_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_conf, app_ram_start); + if (err_code != NRF_SUCCESS) { return err_code; + } + + // TODO set ATT_MTU so that the maximum MTU we can negotiate is higher than the default. + + // This sets app_ram_start to the minimum value needed for the settings set above. + err_code = sd_ble_enable(&app_ram_start); + if (err_code != NRF_SUCCESS) { + return err_code; + } ble_gap_conn_params_t gap_conn_params = { .min_conn_interval = BLE_MIN_CONN_INTERVAL, @@ -122,11 +155,108 @@ STATIC uint32_t ble_stack_enable(void) { return err_code; } -void common_hal_bleio_adapter_set_enabled(bool enabled) { - const bool is_enabled = common_hal_bleio_adapter_get_enabled(); +STATIC bool adapter_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { + bleio_adapter_obj_t *self = (bleio_adapter_obj_t*)self_in; + + // For debugging. + // mp_printf(&mp_plat_print, "Adapter event: 0x%04x\n", ble_evt->header.evt_id); + + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: { + // Find an empty connection + bleio_connection_internal_t *connection; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + connection = &connections[i]; + if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) { + break; + } + } + + // Central has connected. + ble_gap_evt_connected_t* connected = &ble_evt->evt.gap_evt.params.connected; + + connection->conn_handle = ble_evt->evt.gap_evt.conn_handle; + connection->connection_obj = mp_const_none; + ble_drv_add_event_handler_entry(&connection->handler_entry, connection_on_ble_evt, connection); + self->connection_objs = NULL; + + // See if connection interval set by Central is out of range. + // If so, negotiate our preferred range. + ble_gap_conn_params_t conn_params; + sd_ble_gap_ppcp_get(&conn_params); + if (conn_params.min_conn_interval < connected->conn_params.min_conn_interval || + conn_params.min_conn_interval > connected->conn_params.max_conn_interval) { + sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params); + } + self->current_advertising_data = NULL; + break; + } + case BLE_GAP_EVT_DISCONNECTED: { + // Find the connection that was disconnected. + bleio_connection_internal_t *connection; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + connection = &connections[i]; + if (connection->conn_handle == ble_evt->evt.gap_evt.conn_handle) { + break; + } + } + ble_drv_remove_event_handler(connection_on_ble_evt, connection); + connection->conn_handle = BLE_CONN_HANDLE_INVALID; + if (connection->connection_obj != mp_const_none) { + bleio_connection_obj_t* obj = connection->connection_obj; + obj->connection = NULL; + obj->disconnect_reason = ble_evt->evt.gap_evt.params.disconnected.reason; + } + self->connection_objs = NULL; + + break; + } + + case BLE_GAP_EVT_ADV_SET_TERMINATED: + self->current_advertising_data = NULL; + break; + + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled adapter event: 0x%04x\n", ble_evt->header.evt_id); + return false; + break; + } + return true; +} + +STATIC void get_address(bleio_adapter_obj_t *self, ble_gap_addr_t *address) { + uint32_t err_code; + + err_code = sd_ble_gap_addr_get(address); + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg(translate("Failed to get local address")); + } +} + +char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0 , 0}; + +STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) { + uint8_t len = sizeof(default_ble_name) - 1; + + ble_gap_addr_t local_address; + get_address(self, &local_address); + + default_ble_name[len - 4] = nibble_to_hex_lower[local_address.addr[1] >> 4 & 0xf]; + default_ble_name[len - 3] = nibble_to_hex_lower[local_address.addr[1] & 0xf]; + default_ble_name[len - 2] = nibble_to_hex_lower[local_address.addr[0] >> 4 & 0xf]; + default_ble_name[len - 1] = nibble_to_hex_lower[local_address.addr[0] & 0xf]; + default_ble_name[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings + + common_hal_bleio_adapter_set_name(self, (char*) default_ble_name); +} + +void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled) { + const bool is_enabled = common_hal_bleio_adapter_get_enabled(self); // Don't enable or disable twice - if ((is_enabled && enabled) || (!is_enabled && !enabled)) { + if (is_enabled == enabled) { return; } @@ -137,22 +267,34 @@ void common_hal_bleio_adapter_set_enabled(bool enabled) { nrfx_power_uninit(); err_code = ble_stack_enable(); - - // Re-init USB hardware - init_usb_hardware(); } else { err_code = sd_softdevice_disable(); - - // Re-init USB hardware - init_usb_hardware(); } + // Re-init USB hardware + init_usb_hardware(); if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg(translate("Failed to change softdevice state")); + mp_raise_OSError_msg_varg(translate("Failed to change softdevice state, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); + } + + // Add a handler for incoming peripheral connections. + if (enabled) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + connection->conn_handle = BLE_CONN_HANDLE_INVALID; + } + bleio_adapter_reset_name(self); + ble_drv_add_event_handler_entry(&self->handler_entry, adapter_on_ble_evt, self); + } else { + ble_drv_reset(); + self->scan_results = NULL; + self->current_advertising_data = NULL; + self->advertising_data = NULL; + self->scan_response_data = NULL; } } -bool common_hal_bleio_adapter_get_enabled(void) { +bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) { uint8_t is_enabled; const uint32_t err_code = sd_softdevice_is_enabled(&is_enabled); @@ -163,22 +305,11 @@ bool common_hal_bleio_adapter_get_enabled(void) { return is_enabled; } -void get_address(ble_gap_addr_t *address) { - uint32_t err_code; - - common_hal_bleio_adapter_set_enabled(true); - err_code = sd_ble_gap_addr_get(address); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg(translate("Failed to get local address")); - } -} - -bleio_address_obj_t *common_hal_bleio_adapter_get_address(void) { - common_hal_bleio_adapter_set_enabled(true); +bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) { + common_hal_bleio_adapter_set_enabled(self, true); ble_gap_addr_t local_address; - get_address(&local_address); + get_address(self, &local_address); bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t); address->base.type = &bleio_address_type; @@ -187,18 +318,326 @@ bleio_address_obj_t *common_hal_bleio_adapter_get_address(void) { return address; } -mp_obj_t common_hal_bleio_adapter_get_default_name(void) { - common_hal_bleio_adapter_set_enabled(true); - - ble_gap_addr_t local_address; - get_address(&local_address); - - char name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0 }; - - name[sizeof(name) - 4] = nibble_to_hex_lower[local_address.addr[1] >> 4 & 0xf]; - name[sizeof(name) - 3] = nibble_to_hex_lower[local_address.addr[1] & 0xf]; - name[sizeof(name) - 2] = nibble_to_hex_lower[local_address.addr[0] >> 4 & 0xf]; - name[sizeof(name) - 1] = nibble_to_hex_lower[local_address.addr[0] & 0xf]; - - return mp_obj_new_str(name, sizeof(name)); +mp_obj_str_t* common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) { + uint16_t len = 0; + sd_ble_gap_device_name_get(NULL, &len); + uint8_t buf[len]; + uint32_t err_code = sd_ble_gap_device_name_get(buf, &len); + if (err_code != NRF_SUCCESS) { + return NULL; + } + return mp_obj_new_str((char*) buf, len); +} + +void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* name) { + ble_gap_conn_sec_mode_t sec; + sec.lv = 0; + sec.sm = 0; + sd_ble_gap_device_name_set(&sec, (const uint8_t*) name, strlen(name)); +} + +STATIC bool scan_on_ble_evt(ble_evt_t *ble_evt, void *scan_results_in) { + bleio_scanresults_obj_t *scan_results = (bleio_scanresults_obj_t*)scan_results_in; + + if (ble_evt->header.evt_id == BLE_GAP_EVT_TIMEOUT && + ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN) { + shared_module_bleio_scanresults_set_done(scan_results, true); + ble_drv_remove_event_handler(scan_on_ble_evt, scan_results); + return true; + } + + if (ble_evt->header.evt_id != BLE_GAP_EVT_ADV_REPORT) { + return false; + } + ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report; + + shared_module_bleio_scanresults_append(scan_results, + ticks_ms, + report->type.connectable, + report->type.scan_response, + report->rssi, + report->peer_addr.addr, + report->peer_addr.addr_type, + report->data.p_data, + report->data.len); + + const uint32_t err_code = sd_ble_gap_scan_start(NULL, scan_results->common_hal_data); + if (err_code != NRF_SUCCESS) { + // TODO: Pass the error into the scan results so it can throw an exception. + scan_results->done = true; + } + return true; +} + +mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, uint8_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active) { + if (self->scan_results != NULL) { + if (!shared_module_bleio_scanresults_get_done(self->scan_results)) { + mp_raise_RuntimeError(translate("Scan already in progess. Stop with stop_scan.")); + } + self->scan_results = NULL; + } + self->scan_results = shared_module_bleio_new_scanresults(buffer_size, prefixes, prefix_length, minimum_rssi); + size_t max_packet_size = extended ? BLE_GAP_SCAN_BUFFER_EXTENDED_MAX_SUPPORTED : BLE_GAP_SCAN_BUFFER_MAX; + uint8_t *raw_data = m_malloc(sizeof(ble_data_t) + max_packet_size, false); + ble_data_t * sd_data = (ble_data_t *) raw_data; + self->scan_results->common_hal_data = sd_data; + sd_data->len = max_packet_size; + sd_data->p_data = raw_data + sizeof(ble_data_t); + + ble_drv_add_event_handler(scan_on_ble_evt, self->scan_results); + + uint32_t nrf_timeout = SEC_TO_UNITS(timeout, UNIT_10_MS); + if (timeout <= 0.0001) { + nrf_timeout = BLE_GAP_SCAN_TIMEOUT_UNLIMITED; + } + + ble_gap_scan_params_t scan_params = { + .extended = extended, + .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), + .timeout = nrf_timeout, + .window = SEC_TO_UNITS(window, UNIT_0_625_MS), + .scan_phys = BLE_GAP_PHY_1MBPS, + .active = active + }; + uint32_t err_code; + err_code = sd_ble_gap_scan_start(&scan_params, sd_data); + + if (err_code != NRF_SUCCESS) { + self->scan_results = NULL; + ble_drv_remove_event_handler(scan_on_ble_evt, self->scan_results); + mp_raise_OSError_msg_varg(translate("Failed to start scanning, err 0x%04x"), err_code); + } + + return MP_OBJ_FROM_PTR(self->scan_results); +} + +void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) { + sd_ble_gap_scan_stop(); + shared_module_bleio_scanresults_set_done(self->scan_results, true); + ble_drv_remove_event_handler(scan_on_ble_evt, self->scan_results); + self->scan_results = NULL; +} + +typedef struct { + uint16_t conn_handle; + volatile bool done; +} connect_info_t; + +STATIC bool connect_on_ble_evt(ble_evt_t *ble_evt, void *info_in) { + connect_info_t *info = (connect_info_t*)info_in; + + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + info->conn_handle = ble_evt->evt.gap_evt.conn_handle; + info->done = true; + + break; + + case BLE_GAP_EVT_TIMEOUT: + // Handle will be invalid. + info->done = true; + break; + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id); + return false; + break; + } + return true; +} + +mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, bool pair) { + + ble_gap_addr_t addr; + + addr.addr_type = address->type; + mp_buffer_info_t address_buf_info; + mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ); + memcpy(addr.addr, (uint8_t *) address_buf_info.buf, NUM_BLEIO_ADDRESS_BYTES); + + ble_gap_scan_params_t scan_params = { + .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), + .window = MSEC_TO_UNITS(100, UNIT_0_625_MS), + .scan_phys = BLE_GAP_PHY_1MBPS, + // timeout of 0 means no timeout + .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS), + }; + + ble_gap_conn_params_t conn_params = { + .conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS), + .min_conn_interval = MSEC_TO_UNITS(15, UNIT_1_25_MS), + .max_conn_interval = MSEC_TO_UNITS(300, UNIT_1_25_MS), + .slave_latency = 0, // number of conn events + }; + + connect_info_t event_info; + ble_drv_add_event_handler(connect_on_ble_evt, &event_info); + event_info.done = false; + + uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM); + + if (err_code != NRF_SUCCESS) { + ble_drv_remove_event_handler(connect_on_ble_evt, &event_info); + mp_raise_OSError_msg_varg(translate("Failed to start connecting, error 0x%04x"), err_code); + } + + while (!event_info.done) { + RUN_BACKGROUND_TASKS; + } + + ble_drv_remove_event_handler(connect_on_ble_evt, &event_info); + + if (event_info.conn_handle == BLE_CONN_HANDLE_INVALID) { + mp_raise_OSError_msg(translate("Failed to connect: timeout")); + } + + // Make the connection object and return it. + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + if (connection->conn_handle == event_info.conn_handle) { + return bleio_connection_new_from_internal(connection); + } + } + + mp_raise_OSError_msg(translate("Failed to connect: internal error")); + + return mp_const_none; +} + +// The nRF SD 6.1.0 can only do one concurrent advertisement so share the advertising handle. +uint8_t adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; + +STATIC void check_data_fit(size_t data_len) { + if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX) { + mp_raise_ValueError(translate("Data too large for advertisement packet")); + } +} + +uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len) { + if (self->current_advertising_data != NULL && self->current_advertising_data == self->advertising_data) { + return NRF_ERROR_BUSY; + } + + // If the current advertising data isn't owned by the adapter then it must be an internal + // advertisement that we should stop. + if (self->current_advertising_data != NULL) { + common_hal_bleio_adapter_stop_advertising(self); + } + + uint32_t err_code; + ble_gap_adv_params_t adv_params = { + .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), + .properties.type = connectable ? BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED + : BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED, + .duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED, + .filter_policy = BLE_GAP_ADV_FP_ANY, + .primary_phy = BLE_GAP_PHY_1MBPS, + }; + + const ble_gap_adv_data_t ble_gap_adv_data = { + .adv_data.p_data = advertising_data, + .adv_data.len = advertising_data_len, + .scan_rsp_data.p_data = scan_response_data_len > 0 ? scan_response_data : NULL, + .scan_rsp_data.len = scan_response_data_len, + }; + + err_code = sd_ble_gap_adv_set_configure(&adv_handle, &ble_gap_adv_data, &adv_params); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + err_code = sd_ble_gap_adv_start(adv_handle, BLE_CONN_CFG_TAG_CUSTOM); + if (err_code != NRF_SUCCESS) { + return err_code; + } + self->current_advertising_data = advertising_data; + return NRF_SUCCESS; +} + + +void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo) { + if (self->current_advertising_data != NULL && self->current_advertising_data == self->advertising_data) { + mp_raise_OSError_msg(translate("Already advertising.")); + } + // interval value has already been validated. + + uint32_t err_code; + + check_data_fit(advertising_data_bufinfo->len); + check_data_fit(scan_response_data_bufinfo->len); + // The advertising data buffers must not move, because the SoftDevice depends on them. + // So make them long-lived and reuse them onwards. + if (self->advertising_data == NULL) { + self->advertising_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true); + } + if (self->scan_response_data == NULL) { + self->scan_response_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true); + } + + memcpy(self->advertising_data, advertising_data_bufinfo->buf, advertising_data_bufinfo->len); + memcpy(self->scan_response_data, scan_response_data_bufinfo->buf, scan_response_data_bufinfo->len); + + err_code = _common_hal_bleio_adapter_start_advertising(self, connectable, interval, self->advertising_data, advertising_data_bufinfo->len, self->scan_response_data, scan_response_data_bufinfo->len); + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to start advertising, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); + } +} + +void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) { + if (adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET) + return; + + // TODO: Don't actually stop. Switch to advertising CircuitPython if we don't already have a connection. + const uint32_t err_code = sd_ble_gap_adv_stop(adv_handle); + self->current_advertising_data = NULL; + + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) { + mp_raise_OSError_msg_varg(translate("Failed to stop advertising, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); + } +} + +bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + if (connection->conn_handle != BLE_CONN_HANDLE_INVALID) { + return true; + } + } + return false; +} + +mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) { + if (self->connection_objs != NULL) { + return self->connection_objs; + } + size_t total_connected = 0; + mp_obj_t items[BLEIO_TOTAL_CONNECTION_COUNT]; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + if (connection->conn_handle != BLE_CONN_HANDLE_INVALID) { + if (connection->connection_obj == mp_const_none) { + connection->connection_obj = bleio_connection_new_from_internal(connection); + } + items[total_connected] = connection->connection_obj; + total_connected++; + } + } + self->connection_objs = mp_obj_new_tuple(total_connected, items); + return self->connection_objs; +} + +void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) { + gc_collect_root((void**)adapter, sizeof(bleio_adapter_obj_t) / sizeof(size_t)); + gc_collect_root((void**)connections, sizeof(connections) / sizeof(size_t)); +} + +void bleio_adapter_reset(bleio_adapter_obj_t* adapter) { + common_hal_bleio_adapter_stop_scan(adapter); + common_hal_bleio_adapter_stop_advertising(adapter); + adapter->connection_objs = NULL; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + connection->connection_obj = mp_const_none; + } } diff --git a/ports/nrf/common-hal/_bleio/Adapter.h b/ports/nrf/common-hal/_bleio/Adapter.h index 5dcc625406..dca4439908 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.h +++ b/ports/nrf/common-hal/_bleio/Adapter.h @@ -30,9 +30,27 @@ #define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ADAPTER_H #include "py/obj.h" +#include "py/objtuple.h" + +#include "shared-bindings/_bleio/Connection.h" +#include "shared-bindings/_bleio/ScanResults.h" + +#define BLEIO_TOTAL_CONNECTION_COUNT 2 + +extern bleio_connection_internal_t connections[BLEIO_TOTAL_CONNECTION_COUNT]; typedef struct { mp_obj_base_t base; -} super_adapter_obj_t; + uint8_t* advertising_data; + uint8_t* scan_response_data; + uint8_t* current_advertising_data; + bleio_scanresults_obj_t* scan_results; + mp_obj_t name; + mp_obj_tuple_t *connection_objs; + ble_drv_evt_handler_entry_t handler_entry; +} bleio_adapter_obj_t; + +void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter); +void bleio_adapter_reset(bleio_adapter_obj_t* adapter); #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ADAPTER_H diff --git a/ports/nrf/common-hal/_bleio/Central.c b/ports/nrf/common-hal/_bleio/Central.c deleted file mode 100644 index db67b763c6..0000000000 --- a/ports/nrf/common-hal/_bleio/Central.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "ble.h" -#include "ble_drv.h" -#include "ble_hci.h" -#include "nrf_soc.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "shared-bindings/_bleio/__init__.h" -#include "shared-bindings/_bleio/Adapter.h" -#include "shared-bindings/_bleio/Central.h" - -STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) { - bleio_central_obj_t *central = (bleio_central_obj_t*)central_in; - - switch (ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: - central->conn_handle = ble_evt->evt.gap_evt.conn_handle; - central->waiting_to_connect = false; - break; - - case BLE_GAP_EVT_TIMEOUT: - // Handle will be invalid. - central->waiting_to_connect = false; - break; - - case BLE_GAP_EVT_DISCONNECTED: - central->conn_handle = BLE_CONN_HANDLE_INVALID; - break; - - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: - sd_ble_gap_sec_params_reply(central->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); - break; - - case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { - ble_gap_evt_conn_param_update_request_t *request = - &ble_evt->evt.gap_evt.params.conn_param_update_request; - sd_ble_gap_conn_param_update(central->conn_handle, &request->conn_params); - break; - } - default: - // For debugging. - // mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id); - break; - } -} - -void common_hal_bleio_central_construct(bleio_central_obj_t *self) { - common_hal_bleio_adapter_set_enabled(true); - - self->remote_service_list = mp_obj_new_list(0, NULL); - self->conn_handle = BLE_CONN_HANDLE_INVALID; -} - -void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) { - common_hal_bleio_adapter_set_enabled(true); - ble_drv_add_event_handler(central_on_ble_evt, self); - - ble_gap_addr_t addr; - - addr.addr_type = address->type; - mp_buffer_info_t address_buf_info; - mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ); - memcpy(addr.addr, (uint8_t *) address_buf_info.buf, NUM_BLEIO_ADDRESS_BYTES); - - ble_gap_scan_params_t scan_params = { - .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), - .window = MSEC_TO_UNITS(100, UNIT_0_625_MS), - .scan_phys = BLE_GAP_PHY_1MBPS, - // timeout of 0 means no timeout - .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS), - }; - - ble_gap_conn_params_t conn_params = { - .conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS), - .min_conn_interval = MSEC_TO_UNITS(15, UNIT_1_25_MS), - .max_conn_interval = MSEC_TO_UNITS(300, UNIT_1_25_MS), - .slave_latency = 0, // number of conn events - }; - - self->waiting_to_connect = true; - - uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to start connecting, error 0x%04x"), err_code); - } - - while (self->waiting_to_connect) { - RUN_BACKGROUND_TASKS; - } - - if (self->conn_handle == BLE_CONN_HANDLE_INVALID) { - mp_raise_OSError_msg(translate("Failed to connect: timeout")); - } -} - -void common_hal_bleio_central_disconnect(bleio_central_obj_t *self) { - sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); -} - -bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self) { - return self->conn_handle != BLE_CONN_HANDLE_INVALID; -} - -mp_obj_tuple_t *common_hal_bleio_central_discover_remote_services(bleio_central_obj_t *self, mp_obj_t service_uuids_whitelist) { - common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), service_uuids_whitelist); - // Convert to a tuple and then clear the list so the callee will take ownership. - mp_obj_tuple_t *services_tuple = mp_obj_new_tuple(self->remote_service_list->len, - self->remote_service_list->items); - mp_obj_list_clear(self->remote_service_list); - return services_tuple; -} - -mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self) { - return self->remote_service_list; -} diff --git a/ports/nrf/common-hal/_bleio/Characteristic.c b/ports/nrf/common-hal/_bleio/Characteristic.c index e8454d528c..ab765d1ed3 100644 --- a/ports/nrf/common-hal/_bleio/Characteristic.c +++ b/ports/nrf/common-hal/_bleio/Characteristic.c @@ -32,7 +32,7 @@ #include "shared-bindings/_bleio/Descriptor.h" #include "shared-bindings/_bleio/Service.h" -static volatile bleio_characteristic_obj_t *m_read_characteristic; +#include "common-hal/_bleio/Adapter.h" STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_handle) { uint16_t cccd; @@ -53,27 +53,6 @@ STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_hand return cccd; } -STATIC void characteristic_on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { - switch (ble_evt->header.evt_id) { - - // More events may be handled later, so keep this as a switch. - - case BLE_GATTC_EVT_READ_RSP: { - ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp; - if (m_read_characteristic) { - m_read_characteristic->value = mp_obj_new_bytearray(response->len, response->data); - } - // Indicate to busy-wait loop that we've read the attribute value. - m_read_characteristic = NULL; - break; - } - - default: - // For debugging. - // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id); - break; - } -} STATIC void characteristic_gatts_notify_indicate(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, uint16_t hvx_type) { uint16_t hvx_len = bufinfo->len; @@ -103,35 +82,14 @@ STATIC void characteristic_gatts_notify_indicate(uint16_t handle, uint16_t conn_ } } -STATIC void characteristic_gattc_read(bleio_characteristic_obj_t *characteristic) { - const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); - common_hal_bleio_check_connected(conn_handle); - - // Set to NULL in event loop after event. - m_read_characteristic = characteristic; - - ble_drv_add_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic); - - const uint32_t err_code = sd_ble_gattc_read(conn_handle, characteristic->handle, 0); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code); - } - - while (m_read_characteristic != NULL) { - RUN_BACKGROUND_TASKS; - } - - ble_drv_remove_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic); -} - -void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { self->service = service; self->uuid = uuid; self->handle = BLE_GATT_HANDLE_INVALID; self->props = props; self->read_perm = read_perm; self->write_perm = write_perm; - self->descriptor_list = mp_obj_new_list(0, NULL); + self->descriptor_list = NULL; const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX; if (max_length < 0 || max_length > max_length_max) { @@ -141,10 +99,18 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, self->max_length = max_length; self->fixed_length = fixed_length; - common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo); + if (service->is_remote) { + self->handle = handle; + } else { + common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo); + } + + if (initial_value_bufinfo != NULL) { + common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo); + } } -mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) { +bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) { return self->descriptor_list; } @@ -152,19 +118,19 @@ bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_character return self->service; } -mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) { +size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len) { // Do GATT operations only if this characteristic has been added to a registered service. if (self->handle != BLE_GATT_HANDLE_INVALID) { - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); + uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); if (common_hal_bleio_service_get_is_remote(self->service)) { // self->value is set by evt handler. - characteristic_gattc_read(self); + return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len); } else { - self->value = common_hal_bleio_gatts_read(self->handle, conn_handle); + return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len); } } - return self->value; + return 0; } void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { @@ -175,39 +141,40 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_raise_ValueError(translate("Value length > max_length")); } - self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len); - // Do GATT operations only if this characteristic has been added to a registered service. if (self->handle != BLE_GATT_HANDLE_INVALID) { - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); if (common_hal_bleio_service_get_is_remote(self->service)) { + uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); // Last argument is true if write-no-reponse desired. common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, (self->props & CHAR_PROP_WRITE_NO_RESPONSE)); } else { + // Always write the value locally even if no connections are active. + common_hal_bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo); + // Check to see if we need to notify or indicate any active connections. + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + uint16_t conn_handle = connection->conn_handle; + if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) { + continue; + } - bool sent = false; - uint16_t cccd = 0; + uint16_t cccd = 0; - const bool notify = self->props & CHAR_PROP_NOTIFY; - const bool indicate = self->props & CHAR_PROP_INDICATE; - if (notify | indicate) { - cccd = characteristic_get_cccd(self->cccd_handle, conn_handle); - } + const bool notify = self->props & CHAR_PROP_NOTIFY; + const bool indicate = self->props & CHAR_PROP_INDICATE; + if (notify | indicate) { + cccd = characteristic_get_cccd(self->cccd_handle, conn_handle); + } - // It's possible that both notify and indicate are set. - if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { - characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION); - sent = true; - } - if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) { - characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION); - sent = true; - } - - if (!sent) { - common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); + // It's possible that both notify and indicate are set. + if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { + characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION); + } + if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) { + characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION); + } } } } @@ -252,7 +219,8 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t * mp_raise_OSError_msg_varg(translate("Failed to add descriptor, err 0x%04x"), err_code); } - mp_obj_list_append(self->descriptor_list, MP_OBJ_FROM_PTR(descriptor)); + descriptor->next = self->descriptor_list; + self->descriptor_list = descriptor; } void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) { @@ -264,7 +232,7 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, mp_raise_ValueError(translate("Can't set CCCD on local Characteristic")); } - const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); + const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); common_hal_bleio_check_connected(conn_handle); uint16_t cccd_value = diff --git a/ports/nrf/common-hal/_bleio/Characteristic.h b/ports/nrf/common-hal/_bleio/Characteristic.h index 3a7691d07f..bb8f28495e 100644 --- a/ports/nrf/common-hal/_bleio/Characteristic.h +++ b/ports/nrf/common-hal/_bleio/Characteristic.h @@ -29,11 +29,12 @@ #define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTIC_H #include "shared-bindings/_bleio/Attribute.h" +#include "common-hal/_bleio/Descriptor.h" #include "shared-module/_bleio/Characteristic.h" #include "common-hal/_bleio/Service.h" #include "common-hal/_bleio/UUID.h" -typedef struct { +typedef struct _bleio_characteristic_obj { mp_obj_base_t base; // Will be MP_OBJ_NULL before being assigned to a Service. bleio_service_obj_t *service; @@ -45,7 +46,7 @@ typedef struct { bleio_characteristic_properties_t props; bleio_attribute_security_mode_t read_perm; bleio_attribute_security_mode_t write_perm; - mp_obj_list_t *descriptor_list; + bleio_descriptor_obj_t *descriptor_list; uint16_t user_desc_handle; uint16_t cccd_handle; uint16_t sccd_handle; diff --git a/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c index 95794feec0..5f280e121f 100644 --- a/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c @@ -38,6 +38,7 @@ #include "tick.h" #include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Connection.h" #include "common-hal/_bleio/CharacteristicBuffer.h" STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) { @@ -50,7 +51,7 @@ STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *d sd_nvic_critical_region_exit(is_nested_critical_region); } -STATIC void characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) { +STATIC bool characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) { bleio_characteristic_buffer_obj_t *self = (bleio_characteristic_buffer_obj_t *) param; switch (ble_evt->header.evt_id) { case BLE_GATTS_EVT_WRITE: { @@ -75,7 +76,11 @@ STATIC void characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) { } break; } + default: + return false; + break; } + return true; } // Assumes that timeout and buffer_size have been validated before call. @@ -150,6 +155,7 @@ void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_o bool common_hal_bleio_characteristic_buffer_connected(bleio_characteristic_buffer_obj_t *self) { return self->characteristic != NULL && self->characteristic->service != NULL && - self->characteristic->service->device != NULL && - common_hal_bleio_device_get_conn_handle(self->characteristic->service->device) != BLE_CONN_HANDLE_INVALID; + (!self->characteristic->service->is_remote || + (self->characteristic->service->connection != MP_OBJ_NULL && + common_hal_bleio_connection_get_connected(self->characteristic->service->connection))); } diff --git a/ports/nrf/common-hal/_bleio/Connection.c b/ports/nrf/common-hal/_bleio/Connection.c new file mode 100644 index 0000000000..5d3e3ace11 --- /dev/null +++ b/ports/nrf/common-hal/_bleio/Connection.c @@ -0,0 +1,629 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/_bleio/Connection.h" + +#include +#include + +#include "ble.h" +#include "ble_drv.h" +#include "ble_hci.h" +#include "nrf_soc.h" +#include "py/gc.h" +#include "py/objlist.h" +#include "py/objstr.h" +#include "py/qstr.h" +#include "py/runtime.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "shared-bindings/_bleio/Attribute.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/UUID.h" + +#define BLE_ADV_LENGTH_FIELD_SIZE 1 +#define BLE_ADV_AD_TYPE_FIELD_SIZE 1 +#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1 + +static const ble_gap_sec_params_t pairing_sec_params = { + .bond = 1, + .mitm = 0, + .lesc = 0, + .keypress = 0, + .oob = 0, + .io_caps = BLE_GAP_IO_CAPS_NONE, + .min_key_size = 7, + .max_key_size = 16, + .kdist_own = { .enc = 1, .id = 1}, + .kdist_peer = { .enc = 1, .id = 1}, +}; + +static volatile bool m_discovery_in_process; +static volatile bool m_discovery_successful; + +static bleio_service_obj_t *m_char_discovery_service; +static bleio_characteristic_obj_t *m_desc_discovery_characteristic; + +bool dump_events = false; + +bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { + bleio_connection_internal_t *self = (bleio_connection_internal_t*)self_in; + + if (BLE_GAP_EVT_BASE <= ble_evt->header.evt_id && ble_evt->header.evt_id <= BLE_GAP_EVT_LAST && + ble_evt->evt.gap_evt.conn_handle != self->conn_handle) { + return false; + } + if (BLE_GATTS_EVT_BASE <= ble_evt->header.evt_id && ble_evt->header.evt_id <= BLE_GATTS_EVT_LAST && + ble_evt->evt.gatts_evt.conn_handle != self->conn_handle) { + return false; + } + + // For debugging. + if (dump_events) { + mp_printf(&mp_plat_print, "Connection event: 0x%04x\n", ble_evt->header.evt_id); + } + + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_DISCONNECTED: + break; + case BLE_GAP_EVT_CONN_PARAM_UPDATE: // 0x12 + break; + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { + ble_gap_phys_t const phys = { + .rx_phys = BLE_GAP_PHY_AUTO, + .tx_phys = BLE_GAP_PHY_AUTO, + }; + sd_ble_gap_phy_update(ble_evt->evt.gap_evt.conn_handle, &phys); + break; + } + + case BLE_GAP_EVT_PHY_UPDATE: // 0x22 + break; + + case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: + // SoftDevice will respond to a length update request. + sd_ble_gap_data_length_update(self->conn_handle, NULL, NULL); + break; + + case BLE_GAP_EVT_DATA_LENGTH_UPDATE: // 0x24 + break; + + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: { + // We only handle MTU of size BLE_GATT_ATT_MTU_DEFAULT. + sd_ble_gatts_exchange_mtu_reply(self->conn_handle, BLE_GATT_ATT_MTU_DEFAULT); + break; + } + + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0); + break; + + case BLE_GATTS_EVT_HVN_TX_COMPLETE: // Capture this for now. 0x55 + break; + + case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { + ble_gap_evt_conn_param_update_request_t *request = + &ble_evt->evt.gap_evt.params.conn_param_update_request; + sd_ble_gap_conn_param_update(self->conn_handle, &request->conn_params); + break; + } + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { + ble_gap_sec_keyset_t keyset = { + .keys_own = { + .p_enc_key = &self->bonding_keys.own_enc, + .p_id_key = NULL, + .p_sign_key = NULL, + .p_pk = NULL + }, + + .keys_peer = { + .p_enc_key = &self->bonding_keys.peer_enc, + .p_id_key = &self->bonding_keys.peer_id, + .p_sign_key = NULL, + .p_pk = NULL + } + }; + + sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_SUCCESS, + &pairing_sec_params, &keyset); + break; + } + + case BLE_GAP_EVT_LESC_DHKEY_REQUEST: + // TODO for LESC pairing: + // sd_ble_gap_lesc_dhkey_reply(...); + break; + + case BLE_GAP_EVT_AUTH_STATUS: { // 0x19 + // Pairing process completed + ble_gap_evt_auth_status_t* status = &ble_evt->evt.gap_evt.params.auth_status; + if (BLE_GAP_SEC_STATUS_SUCCESS == status->auth_status) { + // TODO _ediv = bonding_keys->own_enc.master_id.ediv; + self->pair_status = PAIR_PAIRED; + } else { + self->pair_status = PAIR_NOT_PAIRED; + } + break; + } + + case BLE_GAP_EVT_SEC_INFO_REQUEST: { // 0x14 + // Peer asks for the stored keys. + // - load key and return if bonded previously. + // - Else return NULL --> Initiate key exchange + ble_gap_evt_sec_info_request_t* sec_info_request = &ble_evt->evt.gap_evt.params.sec_info_request; + (void) sec_info_request; + //if ( bond_load_keys(_role, sec_req->master_id.ediv, &bkeys) ) { + //sd_ble_gap_sec_info_reply(_conn_hdl, &bkeys.own_enc.enc_info, &bkeys.peer_id.id_info, NULL); + // + //_ediv = bkeys.own_enc.master_id.ediv; + // } else { + sd_ble_gap_sec_info_reply(self->conn_handle, NULL, NULL, NULL); + // } + break; + } + + case BLE_GAP_EVT_CONN_SEC_UPDATE: { // 0x1a + ble_gap_conn_sec_t* conn_sec = &ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec; + if (conn_sec->sec_mode.sm <= 1 && conn_sec->sec_mode.lv <= 1) { + // Security setup did not succeed: + // mode 0, level 0 means no access + // mode 1, level 1 means open link + // mode >=1 and/or level >=1 means encryption is set up + self->pair_status = PAIR_NOT_PAIRED; + } else { + //if ( !bond_load_cccd(_role, _conn_hdl, _ediv) ) { + if (true) { // TODO: no bonding yet + // Initialize system attributes fresh. + sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0); + } + // Not quite paired yet: wait for BLE_GAP_EVT_AUTH_STATUS SUCCESS. + self->ediv = self->bonding_keys.own_enc.master_id.ediv; + } + break; + } + + + default: + // For debugging. + if (dump_events) { + mp_printf(&mp_plat_print, "Unhandled connection event: 0x%04x\n", ble_evt->header.evt_id); + } + + return false; + } + return true; +} + +void bleio_connection_clear(bleio_connection_internal_t *self) { + self->remote_service_list = NULL; + + self->conn_handle = BLE_CONN_HANDLE_INVALID; + self->pair_status = PAIR_NOT_PAIRED; + + memset(&self->bonding_keys, 0, sizeof(self->bonding_keys)); +} + +bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self) { + if (self->connection == NULL) { + return false; + } + return self->connection->conn_handle != BLE_CONN_HANDLE_INVALID; +} + +void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self) { + sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); +} + +void common_hal_bleio_connection_pair(bleio_connection_internal_t *self) { + self->pair_status = PAIR_WAITING; + + uint32_t err_code = sd_ble_gap_authenticate(self->conn_handle, &pairing_sec_params); + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to start pairing, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); + } + + while (self->pair_status == PAIR_WAITING) { + RUN_BACKGROUND_TASKS; + } + + if (self->pair_status == PAIR_NOT_PAIRED) { + mp_raise_OSError_msg(translate("Failed to pair")); + } +} + + +// service_uuid may be NULL, to discover all services. +STATIC bool discover_next_services(bleio_connection_internal_t* connection, uint16_t start_handle, ble_uuid_t *service_uuid) { + m_discovery_successful = false; + m_discovery_in_process = true; + + uint32_t err_code = sd_ble_gattc_primary_services_discover(connection->conn_handle, start_handle, service_uuid); + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg(translate("Failed to discover services")); + } + + // Wait for a discovery event. + while (m_discovery_in_process) { + MICROPY_VM_HOOK_LOOP; + } + return m_discovery_successful; +} + +STATIC bool discover_next_characteristics(bleio_connection_internal_t* connection, bleio_service_obj_t *service, uint16_t start_handle) { + m_char_discovery_service = service; + + ble_gattc_handle_range_t handle_range; + handle_range.start_handle = start_handle; + handle_range.end_handle = service->end_handle; + + m_discovery_successful = false; + m_discovery_in_process = true; + + uint32_t err_code = sd_ble_gattc_characteristics_discover(connection->conn_handle, &handle_range); + if (err_code != NRF_SUCCESS) { + return false; + } + + // Wait for a discovery event. + while (m_discovery_in_process) { + MICROPY_VM_HOOK_LOOP; + } + return m_discovery_successful; +} + +STATIC bool discover_next_descriptors(bleio_connection_internal_t* connection, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) { + m_desc_discovery_characteristic = characteristic; + + ble_gattc_handle_range_t handle_range; + handle_range.start_handle = start_handle; + handle_range.end_handle = end_handle; + + m_discovery_successful = false; + m_discovery_in_process = true; + + uint32_t err_code = sd_ble_gattc_descriptors_discover(connection->conn_handle, &handle_range); + if (err_code != NRF_SUCCESS) { + return false; + } + + // Wait for a discovery event. + while (m_discovery_in_process) { + MICROPY_VM_HOOK_LOOP; + } + return m_discovery_successful; +} + +STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_connection_internal_t* connection) { + bleio_service_obj_t* tail = connection->remote_service_list; + + for (size_t i = 0; i < response->count; ++i) { + ble_gattc_service_t *gattc_service = &response->services[i]; + + bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t); + service->base.type = &bleio_service_type; + + // Initialize several fields at once. + bleio_service_from_connection(service, bleio_connection_new_from_internal(connection)); + + service->is_remote = true; + service->start_handle = gattc_service->handle_range.start_handle; + service->end_handle = gattc_service->handle_range.end_handle; + service->handle = gattc_service->handle_range.start_handle; + + if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) { + // Known service UUID. + bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid); + service->uuid = uuid; + } else { + // The discovery response contained a 128-bit UUID that has not yet been registered with the + // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. + // For now, just set the UUID to NULL. + service->uuid = NULL; + } + + service->next = tail; + tail = service; + } + + connection->remote_service_list = tail; + + if (response->count > 0) { + m_discovery_successful = true; + } + m_discovery_in_process = false; +} + +STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio_connection_internal_t* connection) { + for (size_t i = 0; i < response->count; ++i) { + ble_gattc_char_t *gattc_char = &response->chars[i]; + + bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t); + characteristic->base.type = &bleio_characteristic_type; + + bleio_uuid_obj_t *uuid = NULL; + + if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) { + // Known characteristic UUID. + uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid); + } else { + // The discovery response contained a 128-bit UUID that has not yet been registered with the + // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. + // For now, just leave the UUID as NULL. + } + + bleio_characteristic_properties_t props = + (gattc_char->char_props.broadcast ? CHAR_PROP_BROADCAST : 0) | + (gattc_char->char_props.indicate ? CHAR_PROP_INDICATE : 0) | + (gattc_char->char_props.notify ? CHAR_PROP_NOTIFY : 0) | + (gattc_char->char_props.read ? CHAR_PROP_READ : 0) | + (gattc_char->char_props.write ? CHAR_PROP_WRITE : 0) | + (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0); + + // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler. + common_hal_bleio_characteristic_construct( + characteristic, m_char_discovery_service, gattc_char->handle_value, uuid, + props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, + GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc + NULL); + + mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic)); + } + + if (response->count > 0) { + m_discovery_successful = true; + } + m_discovery_in_process = false; +} + +STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio_connection_internal_t* connection) { + for (size_t i = 0; i < response->count; ++i) { + ble_gattc_desc_t *gattc_desc = &response->descs[i]; + + // Remember handles for certain well-known descriptors. + switch (gattc_desc->uuid.uuid) { + case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG: + m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle; + break; + + case BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG: + m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle; + break; + + case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC: + m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle; + break; + + default: + // TODO: sd_ble_gattc_descriptors_discover() can return things that are not descriptors, + // so ignore those. + // https://devzone.nordicsemi.com/f/nordic-q-a/49500/sd_ble_gattc_descriptors_discover-is-returning-attributes-that-are-not-descriptors + break; + } + + bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t); + descriptor->base.type = &bleio_descriptor_type; + + bleio_uuid_obj_t *uuid = NULL; + + if (gattc_desc->uuid.type != BLE_UUID_TYPE_UNKNOWN) { + // Known descriptor UUID. + uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_desc->uuid); + } else { + // The discovery response contained a 128-bit UUID that has not yet been registered with the + // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. + // For now, just leave the UUID as NULL. + } + + common_hal_bleio_descriptor_construct( + descriptor, m_desc_discovery_characteristic, uuid, + SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, + GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes); + descriptor->handle = gattc_desc->handle; + + mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor)); + } + + if (response->count > 0) { + m_discovery_successful = true; + } + m_discovery_in_process = false; +} + +STATIC bool discovery_on_ble_evt(ble_evt_t *ble_evt, mp_obj_t payload) { + bleio_connection_internal_t* connection = MP_OBJ_TO_PTR(payload); + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_DISCONNECTED: + m_discovery_successful = false; + m_discovery_in_process = false; + break; + + case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: + on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, connection); + break; + + case BLE_GATTC_EVT_CHAR_DISC_RSP: + on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, connection); + break; + + case BLE_GATTC_EVT_DESC_DISC_RSP: + on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, connection); + break; + + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled discovery event: 0x%04x\n", ble_evt->header.evt_id); + return false; + break; + } + return true; +} + +STATIC void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t service_uuids_whitelist) { + ble_drv_add_event_handler(discovery_on_ble_evt, self); + + // Start over with an empty list. + self->remote_service_list = NULL; + + if (service_uuids_whitelist == mp_const_none) { + // List of service UUID's not given, so discover all available services. + + uint16_t next_service_start_handle = BLE_GATT_HANDLE_START; + + while (discover_next_services(self, next_service_start_handle, MP_OBJ_NULL)) { + // discover_next_services() appends to remote_services_list. + + // Get the most recently discovered service, and then ask for services + // whose handles start after the last attribute handle inside that service. + const bleio_service_obj_t *service = self->remote_service_list; + next_service_start_handle = service->end_handle + 1; + } + } else { + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(service_uuids_whitelist, &iter_buf); + mp_obj_t uuid_obj; + while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { + mp_raise_ValueError(translate("non-UUID found in service_uuids_whitelist")); + } + bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj); + + ble_uuid_t nrf_uuid; + bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid); + + // Service might or might not be discovered; that's ok. Caller has to check + // Central.remote_services to find out. + // We only need to call this once for each service to discover. + discover_next_services(self, BLE_GATT_HANDLE_START, &nrf_uuid); + } + } + + + bleio_service_obj_t *service = self->remote_service_list; + while (service != NULL) { + // Skip the service if it had an unknown (unregistered) UUID. + if (service->uuid == NULL) { + service = service->next; + continue; + } + + uint16_t next_char_start_handle = service->start_handle; + + // Stop when we go past the end of the range of handles for this service or + // discovery call returns nothing. + // discover_next_characteristics() appends to the characteristic_list. + while (next_char_start_handle <= service->end_handle && + discover_next_characteristics(self, service, next_char_start_handle)) { + + + // Get the most recently discovered characteristic, and then ask for characteristics + // whose handles start after the last attribute handle inside that characteristic. + const bleio_characteristic_obj_t *characteristic = + MP_OBJ_TO_PTR(service->characteristic_list->items[service->characteristic_list->len - 1]); + + next_char_start_handle = characteristic->handle + 1; + } + + // Got characteristics for this service. Now discover descriptors for each characteristic. + size_t char_list_len = service->characteristic_list->len; + for (size_t char_idx = 0; char_idx < char_list_len; ++char_idx) { + bleio_characteristic_obj_t *characteristic = + MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx]); + const bool last_characteristic = char_idx == char_list_len - 1; + bleio_characteristic_obj_t *next_characteristic = last_characteristic + ? NULL + : MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx + 1]); + + // Skip the characteristic if it had an unknown (unregistered) UUID. + if (characteristic->uuid == NULL) { + continue; + } + + uint16_t next_desc_start_handle = characteristic->handle + 1; + + // Don't run past the end of this service or the beginning of the next characteristic. + uint16_t next_desc_end_handle = next_characteristic == NULL + ? service->end_handle + : next_characteristic->handle - 1; + + // Stop when we go past the end of the range of handles for this service or + // discovery call returns nothing. + // discover_next_descriptors() appends to the descriptor_list. + while (next_desc_start_handle <= service->end_handle && + next_desc_start_handle < next_desc_end_handle && + discover_next_descriptors(self, characteristic, + next_desc_start_handle, next_desc_end_handle)) { + + // Get the most recently discovered descriptor, and then ask for descriptors + // whose handles start after that descriptor's handle. + const bleio_descriptor_obj_t *descriptor = characteristic->descriptor_list; + next_desc_start_handle = descriptor->handle + 1; + } + } + service = service->next; + } + + // This event handler is no longer needed. + ble_drv_remove_event_handler(discovery_on_ble_evt, self); + +} +mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist) { + discover_remote_services(self->connection, service_uuids_whitelist); + // Convert to a tuple and then clear the list so the callee will take ownership. + mp_obj_tuple_t *services_tuple = service_linked_list_to_tuple(self->connection->remote_service_list); + self->connection->remote_service_list = NULL; + + return services_tuple; +} + + +uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self) { + if (self == NULL || self->connection == NULL) { + return BLE_CONN_HANDLE_INVALID; + } + return self->connection->conn_handle; +} + +mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t* internal) { + if (internal->connection_obj != mp_const_none) { + return internal->connection_obj; + } + bleio_connection_obj_t *connection = m_new_obj(bleio_connection_obj_t); + connection->base.type = &bleio_connection_type; + connection->connection = internal; + internal->connection_obj = connection; + + return MP_OBJ_FROM_PTR(connection); +} diff --git a/ports/nrf/common-hal/_bleio/Peripheral.h b/ports/nrf/common-hal/_bleio/Connection.h similarity index 67% rename from ports/nrf/common-hal/_bleio/Peripheral.h rename to ports/nrf/common-hal/_bleio/Connection.h index a4f62d288a..2d4aad0c8d 100644 --- a/ports/nrf/common-hal/_bleio/Peripheral.h +++ b/ports/nrf/common-hal/_bleio/Connection.h @@ -25,8 +25,8 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H -#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H +#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CONNECTION_H +#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CONNECTION_H #include @@ -37,6 +37,7 @@ #include "common-hal/_bleio/__init__.h" #include "shared-module/_bleio/Address.h" +#include "common-hal/_bleio/Service.h" typedef enum { PAIR_NOT_PAIRED, @@ -44,24 +45,35 @@ typedef enum { PAIR_PAIRED, } pair_status_t; +// We split the Connection object into two so that the internal mechanics can live outside of the +// VM. If it were one object, then we'd risk user code seeing a connection object of theirs be +// reused. typedef struct { - mp_obj_base_t base; - mp_obj_t name; - volatile uint16_t conn_handle; - // Services provided by this peripheral. - mp_obj_list_t *service_list; + uint16_t conn_handle; + bool is_central; // Remote services discovered when this peripheral is acting as a client. - mp_obj_list_t *remote_service_list; + bleio_service_obj_t *remote_service_list; // The advertising data and scan response buffers are held by us, not by the SD, so we must // maintain them and not change it. If we need to change the contents during advertising, // there are tricks to get the SD to notice (see DevZone - TBS). // EDIV: Encrypted Diversifier: Identifies LTK during legacy pairing. bonding_keys_t bonding_keys; uint16_t ediv; - uint8_t* advertising_data; - uint8_t* scan_response_data; - uint8_t adv_handle; pair_status_t pair_status; -} bleio_peripheral_obj_t; + mp_obj_t connection_obj; + ble_drv_evt_handler_entry_t handler_entry; +} bleio_connection_internal_t; -#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H +typedef struct { + mp_obj_base_t base; + bleio_connection_internal_t* connection; + // The HCI disconnect reason. + uint8_t disconnect_reason; +} bleio_connection_obj_t; + +bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in); + +uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); +mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t* connection); + +#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CONNECTION_H diff --git a/ports/nrf/common-hal/_bleio/Descriptor.c b/ports/nrf/common-hal/_bleio/Descriptor.c index 137f004bab..faf50c658c 100644 --- a/ports/nrf/common-hal/_bleio/Descriptor.c +++ b/ports/nrf/common-hal/_bleio/Descriptor.c @@ -33,8 +33,6 @@ #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" -static volatile bleio_descriptor_obj_t *m_read_descriptor; - void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { self->characteristic = characteristic; self->uuid = uuid; @@ -61,62 +59,18 @@ bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio return self->characteristic; } -STATIC void descriptor_on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { - switch (ble_evt->header.evt_id) { - - // More events may be handled later, so keep this as a switch. - - case BLE_GATTC_EVT_READ_RSP: { - ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp; - if (m_read_descriptor) { - m_read_descriptor->value = mp_obj_new_bytearray(response->len, response->data); - } - // Indicate to busy-wait loop that we've read the attribute value. - m_read_descriptor = NULL; - break; - } - - default: - // For debugging. - // mp_printf(&mp_plat_print, "Unhandled descriptor event: 0x%04x\n", ble_evt->header.evt_id); - break; - } -} - -STATIC void descriptor_gattc_read(bleio_descriptor_obj_t *descriptor) { - const uint16_t conn_handle = - common_hal_bleio_device_get_conn_handle(descriptor->characteristic->service->device); - common_hal_bleio_check_connected(conn_handle); - - // Set to NULL in event loop after event. - m_read_descriptor = descriptor; - - ble_drv_add_event_handler(descriptor_on_gattc_read_rsp_evt, descriptor); - - const uint32_t err_code = sd_ble_gattc_read(conn_handle, descriptor->handle, 0); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code); - } - - while (m_read_descriptor != NULL) { - MICROPY_VM_HOOK_LOOP; - } - - ble_drv_remove_event_handler(descriptor_on_gattc_read_rsp_evt, descriptor); -} - -mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self) { +size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t* buf, size_t len) { // Do GATT operations only if this descriptor has been registered if (self->handle != BLE_GATT_HANDLE_INVALID) { + uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { - descriptor_gattc_read(self); + return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len); } else { - self->value = common_hal_bleio_gatts_read( - self->handle, common_hal_bleio_device_get_conn_handle(self->characteristic->service->device)); + return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len); } } - return self->value; + return 0; } void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) { @@ -131,7 +85,7 @@ void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buff // Do GATT operations only if this descriptor has been registered. if (self->handle != BLE_GATT_HANDLE_INVALID) { - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->characteristic->service->device); + uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { // false means WRITE_REQ, not write-no-response common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false); diff --git a/ports/nrf/common-hal/_bleio/Descriptor.h b/ports/nrf/common-hal/_bleio/Descriptor.h index 3adb0df184..c70547c08e 100644 --- a/ports/nrf/common-hal/_bleio/Descriptor.h +++ b/ports/nrf/common-hal/_bleio/Descriptor.h @@ -31,13 +31,15 @@ #include "py/obj.h" -#include "common-hal/_bleio/Characteristic.h" #include "common-hal/_bleio/UUID.h" -typedef struct { +// Forward declare characteristic because it includes a Descriptor. +struct _bleio_characteristic_obj; + +typedef struct _bleio_descriptor_obj { mp_obj_base_t base; // Will be MP_OBJ_NULL before being assigned to a Characteristic. - bleio_characteristic_obj_t *characteristic; + struct _bleio_characteristic_obj *characteristic; bleio_uuid_obj_t *uuid; mp_obj_t value; uint16_t max_length; @@ -45,6 +47,7 @@ typedef struct { uint16_t handle; bleio_attribute_security_mode_t read_perm; bleio_attribute_security_mode_t write_perm; + struct _bleio_descriptor_obj* next; } bleio_descriptor_obj_t; #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H diff --git a/ports/nrf/common-hal/_bleio/Peripheral.c b/ports/nrf/common-hal/_bleio/Peripheral.c deleted file mode 100644 index 9b0f96d48f..0000000000 --- a/ports/nrf/common-hal/_bleio/Peripheral.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "ble.h" -#include "ble_drv.h" -#include "ble_hci.h" -#include "nrf_soc.h" -#include "py/gc.h" -#include "py/objlist.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "shared-bindings/_bleio/__init__.h" -#include "shared-bindings/_bleio/Adapter.h" -#include "shared-bindings/_bleio/Attribute.h" -#include "shared-bindings/_bleio/Characteristic.h" -#include "shared-bindings/_bleio/Peripheral.h" -#include "shared-bindings/_bleio/Service.h" -#include "shared-bindings/_bleio/UUID.h" - -#define BLE_ADV_LENGTH_FIELD_SIZE 1 -#define BLE_ADV_AD_TYPE_FIELD_SIZE 1 -#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1 - -static const ble_gap_sec_params_t pairing_sec_params = { - .bond = 1, - .mitm = 0, - .lesc = 0, - .keypress = 0, - .oob = 0, - .io_caps = BLE_GAP_IO_CAPS_NONE, - .min_key_size = 7, - .max_key_size = 16, - .kdist_own = { .enc = 1, .id = 1}, - .kdist_peer = { .enc = 1, .id = 1}, -}; - -STATIC void check_data_fit(size_t data_len) { - if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX) { - mp_raise_ValueError(translate("Data too large for advertisement packet")); - } -} - -STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { - bleio_peripheral_obj_t *self = (bleio_peripheral_obj_t*)self_in; - - // For debugging. - // mp_printf(&mp_plat_print, "Peripheral event: 0x%04x\n", ble_evt->header.evt_id); - - switch (ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: { - // Central has connected. - ble_gap_evt_connected_t* connected = &ble_evt->evt.gap_evt.params.connected; - - self->conn_handle = ble_evt->evt.gap_evt.conn_handle; - - // See if connection interval set by Central is out of range. - // If so, negotiate our preferred range. - ble_gap_conn_params_t conn_params; - sd_ble_gap_ppcp_get(&conn_params); - if (conn_params.min_conn_interval < connected->conn_params.min_conn_interval || - conn_params.min_conn_interval > connected->conn_params.max_conn_interval) { - sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params); - } - break; - } - - case BLE_GAP_EVT_DISCONNECTED: - // Central has disconnected. - self->conn_handle = BLE_CONN_HANDLE_INVALID; - break; - - case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { - ble_gap_phys_t const phys = { - .rx_phys = BLE_GAP_PHY_AUTO, - .tx_phys = BLE_GAP_PHY_AUTO, - }; - sd_ble_gap_phy_update(ble_evt->evt.gap_evt.conn_handle, &phys); - break; - } - - case BLE_GAP_EVT_ADV_SET_TERMINATED: - // TODO: Someday may handle timeouts or limit reached. - break; - - case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: - // SoftDevice will respond to a length update request. - sd_ble_gap_data_length_update(self->conn_handle, NULL, NULL); - break; - - case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: { - // We only handle MTU of size BLE_GATT_ATT_MTU_DEFAULT. - sd_ble_gatts_exchange_mtu_reply(self->conn_handle, BLE_GATT_ATT_MTU_DEFAULT); - break; - } - - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0); - break; - - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { - ble_gap_sec_keyset_t keyset = { - .keys_own = { - .p_enc_key = &self->bonding_keys.own_enc, - .p_id_key = NULL, - .p_sign_key = NULL, - .p_pk = NULL - }, - - .keys_peer = { - .p_enc_key = &self->bonding_keys.peer_enc, - .p_id_key = &self->bonding_keys.peer_id, - .p_sign_key = NULL, - .p_pk = NULL - } - }; - - sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_SUCCESS, - &pairing_sec_params, &keyset); - break; - } - - case BLE_GAP_EVT_LESC_DHKEY_REQUEST: - // TODO for LESC pairing: - // sd_ble_gap_lesc_dhkey_reply(...); - break; - - case BLE_GAP_EVT_AUTH_STATUS: { - // Pairing process completed - ble_gap_evt_auth_status_t* status = &ble_evt->evt.gap_evt.params.auth_status; - if (BLE_GAP_SEC_STATUS_SUCCESS == status->auth_status) { - // TODO _ediv = bonding_keys->own_enc.master_id.ediv; - self->pair_status = PAIR_PAIRED; - } else { - self->pair_status = PAIR_NOT_PAIRED; - } - break; - } - - case BLE_GAP_EVT_SEC_INFO_REQUEST: { - // Peer asks for the stored keys. - // - load key and return if bonded previously. - // - Else return NULL --> Initiate key exchange - ble_gap_evt_sec_info_request_t* sec_info_request = &ble_evt->evt.gap_evt.params.sec_info_request; - (void) sec_info_request; - //if ( bond_load_keys(_role, sec_req->master_id.ediv, &bkeys) ) { - //sd_ble_gap_sec_info_reply(_conn_hdl, &bkeys.own_enc.enc_info, &bkeys.peer_id.id_info, NULL); - // - //_ediv = bkeys.own_enc.master_id.ediv; - // } else { - sd_ble_gap_sec_info_reply(self->conn_handle, NULL, NULL, NULL); - // } - break; - } - - case BLE_GAP_EVT_CONN_SEC_UPDATE: { - ble_gap_conn_sec_t* conn_sec = &ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec; - if (conn_sec->sec_mode.sm <= 1 && conn_sec->sec_mode.lv <= 1) { - // Security setup did not succeed: - // mode 0, level 0 means no access - // mode 1, level 1 means open link - // mode >=1 and/or level >=1 means encryption is set up - self->pair_status = PAIR_NOT_PAIRED; - } else { - //if ( !bond_load_cccd(_role, _conn_hdl, _ediv) ) { - if (true) { // TODO: no bonding yet - // Initialize system attributes fresh. - sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0); - } - // Not quite paired yet: wait for BLE_GAP_EVT_AUTH_STATUS SUCCESS. - self->ediv = self->bonding_keys.own_enc.master_id.ediv; - } - break; - } - - - default: - // For debugging. - // mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id); - break; - } -} - -void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_t name) { - common_hal_bleio_adapter_set_enabled(true); - - self->service_list = mp_obj_new_list(0, NULL); - // Used only for discovery when acting as a client. - self->remote_service_list = mp_obj_new_list(0, NULL); - self->name = name; - - self->conn_handle = BLE_CONN_HANDLE_INVALID; - self->adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; - self->pair_status = PAIR_NOT_PAIRED; - - memset(&self->bonding_keys, 0, sizeof(self->bonding_keys)); -} - -void common_hal_bleio_peripheral_add_service(bleio_peripheral_obj_t *self, bleio_service_obj_t *service) { - ble_uuid_t uuid; - bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid); - - uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY; - if (common_hal_bleio_service_get_is_secondary(service)) { - service_type = BLE_GATTS_SRVC_TYPE_SECONDARY; - } - - const uint32_t err_code = sd_ble_gatts_service_add(service_type, &uuid, &service->handle); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to add service, err 0x%04x"), err_code); - } - - mp_obj_list_append(self->service_list, MP_OBJ_FROM_PTR(service)); -} - -mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self) { - return self->service_list; -} - -bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self) { - return self->conn_handle != BLE_CONN_HANDLE_INVALID; -} - -mp_obj_t common_hal_bleio_peripheral_get_name(bleio_peripheral_obj_t *self) { - return self->name; -} - -void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo) { - - // interval value has already been validated. - - if (connectable) { - ble_drv_add_event_handler(peripheral_on_ble_evt, self); - } - - common_hal_bleio_adapter_set_enabled(true); - - uint32_t err_code; - - GET_STR_DATA_LEN(self->name, name_data, name_len); - if (name_len > 0) { - // Set device name, and make it available to anyone. - ble_gap_conn_sec_mode_t sec_mode; - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); - err_code = sd_ble_gap_device_name_set(&sec_mode, name_data, name_len); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to set device name, err 0x%04x"), err_code); - - } - } - - check_data_fit(advertising_data_bufinfo->len); - // The advertising data buffers must not move, because the SoftDevice depends on them. - // So make them long-lived. - self->advertising_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true); - memcpy(self->advertising_data, advertising_data_bufinfo->buf, advertising_data_bufinfo->len); - - check_data_fit(scan_response_data_bufinfo->len); - self->scan_response_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true); - memcpy(self->scan_response_data, scan_response_data_bufinfo->buf, scan_response_data_bufinfo->len); - - - ble_gap_adv_params_t adv_params = { - .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), - .properties.type = connectable ? BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED - : BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED, - .duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED, - .filter_policy = BLE_GAP_ADV_FP_ANY, - .primary_phy = BLE_GAP_PHY_1MBPS, - }; - - common_hal_bleio_peripheral_stop_advertising(self); - - const ble_gap_adv_data_t ble_gap_adv_data = { - .adv_data.p_data = self->advertising_data, - .adv_data.len = advertising_data_bufinfo->len, - .scan_rsp_data.p_data = scan_response_data_bufinfo-> len > 0 ? self->scan_response_data : NULL, - .scan_rsp_data.len = scan_response_data_bufinfo->len, - }; - - err_code = sd_ble_gap_adv_set_configure(&self->adv_handle, &ble_gap_adv_data, &adv_params); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to configure advertising, err 0x%04x"), err_code); - } - - err_code = sd_ble_gap_adv_start(self->adv_handle, BLE_CONN_CFG_TAG_CUSTOM); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to start advertising, err 0x%04x"), err_code); - } -} - -void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *self) { - if (self->adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET) - return; - - const uint32_t err_code = sd_ble_gap_adv_stop(self->adv_handle); - - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) { - mp_raise_OSError_msg_varg(translate("Failed to stop advertising, err 0x%04x"), err_code); - } -} - -void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *self) { - sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); -} - -mp_obj_tuple_t *common_hal_bleio_peripheral_discover_remote_services(bleio_peripheral_obj_t *self, mp_obj_t service_uuids_whitelist) { - common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), service_uuids_whitelist); - // Convert to a tuple and then clear the list so the callee will take ownership. - mp_obj_tuple_t *services_tuple = mp_obj_new_tuple(self->remote_service_list->len, - self->remote_service_list->items); - mp_obj_list_clear(self->remote_service_list); - return services_tuple; -} - -void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *self) { - self->pair_status = PAIR_WAITING; - - uint32_t err_code = sd_ble_gap_authenticate(self->conn_handle, &pairing_sec_params); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to start pairing, error 0x%04x"), err_code); - } - - while (self->pair_status == PAIR_WAITING) { - RUN_BACKGROUND_TASKS; - } - - if (self->pair_status == PAIR_NOT_PAIRED) { - mp_raise_OSError_msg(translate("Failed to pair")); - } - - -} diff --git a/ports/nrf/common-hal/_bleio/Scanner.c b/ports/nrf/common-hal/_bleio/Scanner.c deleted file mode 100644 index ec73f7eb8f..0000000000 --- a/ports/nrf/common-hal/_bleio/Scanner.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * Copyright (c) 2016 Glenn Ruben Bakke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include - -#include "ble_drv.h" -#include "ble_gap.h" -#include "py/mphal.h" -#include "py/objlist.h" -#include "py/runtime.h" -#include "shared-bindings/_bleio/Adapter.h" -#include "shared-bindings/_bleio/ScanEntry.h" -#include "shared-bindings/_bleio/Scanner.h" -#include "shared-module/_bleio/ScanEntry.h" - -static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN]; - -static ble_data_t m_scan_buffer = { - m_scan_buffer_data, - BLE_GAP_SCAN_BUFFER_MIN -}; - -STATIC void scanner_on_ble_evt(ble_evt_t *ble_evt, void *scanner_in) { - bleio_scanner_obj_t *scanner = (bleio_scanner_obj_t*)scanner_in; - ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report; - - if (ble_evt->header.evt_id != BLE_GAP_EVT_ADV_REPORT) { - return; - } - - bleio_scanentry_obj_t *entry = m_new_obj(bleio_scanentry_obj_t); - entry->base.type = &bleio_scanentry_type; - entry->rssi = report->rssi; - - bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t); - address->base.type = &bleio_address_type; - common_hal_bleio_address_construct(MP_OBJ_TO_PTR(address), - report->peer_addr.addr, report->peer_addr.addr_type); - entry->address = address; - - entry->data = mp_obj_new_bytes(report->data.p_data, report->data.len); - - mp_obj_list_append(scanner->scan_entries, MP_OBJ_FROM_PTR(entry)); - - const uint32_t err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to continue scanning, err 0x%04x"), err_code); - } -} - -void common_hal_bleio_scanner_construct(bleio_scanner_obj_t *self) { -} - -mp_obj_t common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_float_t timeout, mp_float_t interval, mp_float_t window) { - common_hal_bleio_adapter_set_enabled(true); - ble_drv_add_event_handler(scanner_on_ble_evt, self); - - ble_gap_scan_params_t scan_params = { - .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), - .window = SEC_TO_UNITS(window, UNIT_0_625_MS), - .scan_phys = BLE_GAP_PHY_1MBPS, - }; - - self->scan_entries = mp_obj_new_list(0, NULL); - - uint32_t err_code; - err_code = sd_ble_gap_scan_start(&scan_params, &m_scan_buffer); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to start scanning, err 0x%04x"), err_code); - } - - mp_hal_delay_ms(timeout * 1000); - sd_ble_gap_scan_stop(); - - // Return list, and don't hang on to it, so it can be GC'd. - mp_obj_t entries = self->scan_entries; - self->scan_entries = MP_OBJ_NULL; - return entries; -} diff --git a/ports/nrf/common-hal/_bleio/Service.c b/ports/nrf/common-hal/_bleio/Service.c index 650cdc4ec9..3362ed1373 100644 --- a/ports/nrf/common-hal/_bleio/Service.c +++ b/ports/nrf/common-hal/_bleio/Service.c @@ -31,17 +31,44 @@ #include "common-hal/_bleio/__init__.h" #include "shared-bindings/_bleio/Characteristic.h" #include "shared-bindings/_bleio/Descriptor.h" -#include "shared-bindings/_bleio/Peripheral.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/Adapter.h" -void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_peripheral_obj_t *peripheral, bleio_uuid_obj_t *uuid, bool is_secondary) { - self->device = MP_OBJ_FROM_PTR(peripheral); +uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t * characteristic_list) { self->handle = 0xFFFF; self->uuid = uuid; - self->characteristic_list = mp_obj_new_list(0, NULL); + self->characteristic_list = characteristic_list; self->is_remote = false; + self->connection = NULL; self->is_secondary = is_secondary; + + ble_uuid_t nordic_uuid; + bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nordic_uuid); + + uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY; + if (is_secondary) { + service_type = BLE_GATTS_SRVC_TYPE_SECONDARY; + } + + vm_used_ble = true; + + return sd_ble_gatts_service_add(service_type, &nordic_uuid, &self->handle); +} + +void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) { + const uint32_t err_code = _common_hal_bleio_service_construct(self, uuid, is_secondary, mp_obj_new_list(0, NULL)); + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to create service, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); + } +} + +void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection) { + self->handle = 0xFFFF; + self->uuid = NULL; + self->characteristic_list = mp_obj_new_list(0, NULL); + self->is_remote = true; + self->is_secondary = false; + self->connection = connection; } bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) { @@ -60,7 +87,9 @@ bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) { return self->is_secondary; } -void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic) { +void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, + bleio_characteristic_obj_t *characteristic, + mp_buffer_info_t *initial_value_bufinfo) { ble_gatts_char_md_t char_md = { .char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0, .char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0, @@ -93,14 +122,11 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, blei bleio_attribute_gatts_set_security_mode(&char_attr_md.read_perm, characteristic->read_perm); bleio_attribute_gatts_set_security_mode(&char_attr_md.write_perm, characteristic->write_perm); - mp_buffer_info_t char_value_bufinfo; - mp_get_buffer_raise(characteristic->value, &char_value_bufinfo, MP_BUFFER_READ); - ble_gatts_attr_t char_attr = { .p_uuid = &char_uuid, .p_attr_md = &char_attr_md, - .init_len = char_value_bufinfo.len, - .p_value = char_value_bufinfo.buf, + .init_len = 0, + .p_value = NULL, .init_offs = 0, .max_len = characteristic->max_length, }; @@ -110,7 +136,7 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, blei uint32_t err_code; err_code = sd_ble_gatts_characteristic_add(self->handle, &char_md, &char_attr, &char_handles); if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to add characteristic, err 0x%04x"), err_code); + mp_raise_OSError_msg_varg(translate("Failed to add characteristic, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); } characteristic->user_desc_handle = char_handles.user_desc_handle; diff --git a/ports/nrf/common-hal/_bleio/Service.h b/ports/nrf/common-hal/_bleio/Service.h index a4614b9f51..f101bc825b 100644 --- a/ports/nrf/common-hal/_bleio/Service.h +++ b/ports/nrf/common-hal/_bleio/Service.h @@ -31,20 +31,22 @@ #include "py/objlist.h" #include "common-hal/_bleio/UUID.h" -typedef struct { +typedef struct bleio_service_obj { mp_obj_base_t base; - // Handle for this service. + // Handle for the local service. uint16_t handle; // True if created during discovery. bool is_remote; bool is_secondary; bleio_uuid_obj_t *uuid; - // May be a Peripheral, Central, etc. - mp_obj_t device; + mp_obj_t connection; mp_obj_list_t *characteristic_list; - // Range of attribute handles of this service. + // Range of attribute handles of this remote service. uint16_t start_handle; uint16_t end_handle; + struct bleio_service_obj* next; } bleio_service_obj_t; +void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection); + #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SERVICE_H diff --git a/ports/nrf/common-hal/_bleio/UUID.c b/ports/nrf/common-hal/_bleio/UUID.c index 0e65b7d58d..5bf35e6a54 100644 --- a/ports/nrf/common-hal/_bleio/UUID.c +++ b/ports/nrf/common-hal/_bleio/UUID.c @@ -30,6 +30,7 @@ #include "py/runtime.h" #include "common-hal/_bleio/UUID.h" +#include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Adapter.h" #include "ble.h" @@ -39,9 +40,7 @@ // If uuid128 is NULL, this is a Bluetooth SIG 16-bit UUID. // If uuid128 is not NULL, it's a 128-bit (16-byte) UUID, with bytes 12 and 13 zero'd out, where // the 16-bit part goes. Those 16 bits are passed in uuid16. -void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, uint32_t uuid16, uint8_t uuid128[]) { - common_hal_bleio_adapter_set_enabled(true); - +void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, uint32_t uuid16, const uint8_t uuid128[]) { self->nrf_ble_uuid.uuid = uuid16; if (uuid128 == NULL) { self->nrf_ble_uuid.type = BLE_UUID_TYPE_BLE; @@ -54,6 +53,7 @@ void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, uint32_t uuid16, ui if (err_code != NRF_SUCCESS) { mp_raise_OSError_msg_varg(translate("Failed to register Vendor-Specific UUID, err 0x%04x"), err_code); } + vm_used_ble = true; } } @@ -65,25 +65,24 @@ uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) { return self->nrf_ble_uuid.uuid; } -// True if uuid128 has been successfully filled in. -bool common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) { +void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) { uint8_t length; const uint32_t err_code = sd_ble_uuid_encode(&self->nrf_ble_uuid, &length, uuid128); if (err_code != NRF_SUCCESS) { mp_raise_OSError_msg_varg(translate("Could not decode ble_uuid, err 0x%04x"), err_code); } - // If not 16 bytes, this is not a 128-bit UUID, so return. - return length == 16; } -// Returns 0 if this is a 16-bit UUID, otherwise returns a non-zero index -// into the 128-bit uuid registration table. -uint32_t common_hal_bleio_uuid_get_uuid128_reference(bleio_uuid_obj_t *self) { - return self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE ? 0 : self->nrf_ble_uuid.type; +void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf) { + if (self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE) { + buf[0] = self->nrf_ble_uuid.uuid & 0xff; + buf[1] = self->nrf_ble_uuid.uuid >> 8; + } else { + common_hal_bleio_uuid_get_uuid128(self, buf); + } } - void bleio_uuid_construct_from_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_ble_uuid) { if (nrf_ble_uuid->type == BLE_UUID_TYPE_UNKNOWN) { mp_raise_RuntimeError(translate("Unexpected nrfx uuid type")); diff --git a/ports/nrf/common-hal/_bleio/__init__.c b/ports/nrf/common-hal/_bleio/__init__.c index 5530441909..1e07ea969c 100644 --- a/ports/nrf/common-hal/_bleio/__init__.c +++ b/ports/nrf/common-hal/_bleio/__init__.c @@ -26,34 +26,58 @@ * THE SOFTWARE. */ +#include + #include "py/runtime.h" #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Adapter.h" -#include "shared-bindings/_bleio/Central.h" #include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Connection.h" #include "shared-bindings/_bleio/Descriptor.h" -#include "shared-bindings/_bleio/Peripheral.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" +#include "supervisor/shared/bluetooth.h" #include "common-hal/_bleio/__init__.h" -static volatile bool m_discovery_in_process; -static volatile bool m_discovery_successful; - -static bleio_service_obj_t *m_char_discovery_service; -static bleio_characteristic_obj_t *m_desc_discovery_characteristic; +const mp_obj_t base_error_messages[20] = { + MP_ROM_QSTR(MP_QSTR_SUCCESS), + MP_ROM_QSTR(MP_QSTR_SVC_HANDLER_MISSING), + MP_ROM_QSTR(MP_QSTR_SOFTDEVICE_NOT_ENABLED), + MP_ROM_QSTR(MP_QSTR_INTERNAL), + MP_ROM_QSTR(MP_QSTR_NO_MEM), + MP_ROM_QSTR(MP_QSTR_NOT_FOUND), + MP_ROM_QSTR(MP_QSTR_NOT_SUPPORTED), + MP_ROM_QSTR(MP_QSTR_INVALID_PARAM), + MP_ROM_QSTR(MP_QSTR_INVALID_STATE), + MP_ROM_QSTR(MP_QSTR_INVALID_LENGTH), + MP_ROM_QSTR(MP_QSTR_INVALID_FLAGS), + MP_ROM_QSTR(MP_QSTR_INVALID_DATA), + MP_ROM_QSTR(MP_QSTR_DATA_SIZE), + MP_ROM_QSTR(MP_QSTR_TIMEOUT), + MP_ROM_QSTR(MP_QSTR_NULL), + MP_ROM_QSTR(MP_QSTR_FORBIDDEN), + MP_ROM_QSTR(MP_QSTR_INVALID_ADDR), + MP_ROM_QSTR(MP_QSTR_BUSY), + MP_ROM_QSTR(MP_QSTR_CONN_COUNT), + MP_ROM_QSTR(MP_QSTR_RESOURCES), +}; // Turn off BLE on a reset or reload. void bleio_reset() { - if (common_hal_bleio_adapter_get_enabled()) { - common_hal_bleio_adapter_set_enabled(false); + bleio_adapter_reset(&common_hal_bleio_adapter_obj); + if (!vm_used_ble) { + return; } + if (common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { + common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false); + } + supervisor_start_bluetooth(); } // The singleton _bleio.Adapter object, bound to _bleio.adapter // It currently only has properties and no state -const super_adapter_obj_t common_hal_bleio_adapter_obj = { +bleio_adapter_obj_t common_hal_bleio_adapter_obj = { .base = { .type = &bleio_adapter_type, }, @@ -65,395 +89,22 @@ void common_hal_bleio_check_connected(uint16_t conn_handle) { } } -uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) { - if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) { - return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle; - } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) { - return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle; - } else { - return BLE_CONN_HANDLE_INVALID; - } -} - -mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device) { - if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) { - return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->remote_service_list; - } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) { - return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->remote_service_list; - } else { - return NULL; - } -} - -// service_uuid may be NULL, to discover all services. -STATIC bool discover_next_services(mp_obj_t device, uint16_t start_handle, ble_uuid_t *service_uuid) { - m_discovery_successful = false; - m_discovery_in_process = true; - - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device); - uint32_t err_code = sd_ble_gattc_primary_services_discover(conn_handle, start_handle, service_uuid); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg(translate("Failed to discover services")); - } - - // Wait for a discovery event. - while (m_discovery_in_process) { - MICROPY_VM_HOOK_LOOP; - } - return m_discovery_successful; -} - -STATIC bool discover_next_characteristics(mp_obj_t device, bleio_service_obj_t *service, uint16_t start_handle) { - m_char_discovery_service = service; - - ble_gattc_handle_range_t handle_range; - handle_range.start_handle = start_handle; - handle_range.end_handle = service->end_handle; - - m_discovery_successful = false; - m_discovery_in_process = true; - - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device); - uint32_t err_code = sd_ble_gattc_characteristics_discover(conn_handle, &handle_range); - if (err_code != NRF_SUCCESS) { - return false; - } - - // Wait for a discovery event. - while (m_discovery_in_process) { - MICROPY_VM_HOOK_LOOP; - } - return m_discovery_successful; -} - -STATIC bool discover_next_descriptors(mp_obj_t device, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) { - m_desc_discovery_characteristic = characteristic; - - ble_gattc_handle_range_t handle_range; - handle_range.start_handle = start_handle; - handle_range.end_handle = end_handle; - - m_discovery_successful = false; - m_discovery_in_process = true; - - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device); - uint32_t err_code = sd_ble_gattc_descriptors_discover(conn_handle, &handle_range); - if (err_code != NRF_SUCCESS) { - return false; - } - - // Wait for a discovery event. - while (m_discovery_in_process) { - MICROPY_VM_HOOK_LOOP; - } - return m_discovery_successful; -} - -STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, mp_obj_t device) { - for (size_t i = 0; i < response->count; ++i) { - ble_gattc_service_t *gattc_service = &response->services[i]; - - bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t); - service->base.type = &bleio_service_type; - - // Initialize several fields at once. - common_hal_bleio_service_construct(service, device, NULL, false); - - service->is_remote = true; - service->start_handle = gattc_service->handle_range.start_handle; - service->end_handle = gattc_service->handle_range.end_handle; - service->handle = gattc_service->handle_range.start_handle; - - if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) { - // Known service UUID. - bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); - uuid->base.type = &bleio_uuid_type; - bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid); - service->uuid = uuid; - } else { - // The discovery response contained a 128-bit UUID that has not yet been registered with the - // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. - // For now, just set the UUID to NULL. - service->uuid = NULL; - } - - mp_obj_list_append(common_hal_bleio_device_get_remote_service_list(device), service); - } - - if (response->count > 0) { - m_discovery_successful = true; - } - m_discovery_in_process = false; -} - -STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_obj_t device) { - for (size_t i = 0; i < response->count; ++i) { - ble_gattc_char_t *gattc_char = &response->chars[i]; - - bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t); - characteristic->base.type = &bleio_characteristic_type; - - bleio_uuid_obj_t *uuid = NULL; - - if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) { - // Known characteristic UUID. - uuid = m_new_obj(bleio_uuid_obj_t); - uuid->base.type = &bleio_uuid_type; - bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid); - } else { - // The discovery response contained a 128-bit UUID that has not yet been registered with the - // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. - // For now, just leave the UUID as NULL. - } - - bleio_characteristic_properties_t props = - (gattc_char->char_props.broadcast ? CHAR_PROP_BROADCAST : 0) | - (gattc_char->char_props.indicate ? CHAR_PROP_INDICATE : 0) | - (gattc_char->char_props.notify ? CHAR_PROP_NOTIFY : 0) | - (gattc_char->char_props.read ? CHAR_PROP_READ : 0) | - (gattc_char->char_props.write ? CHAR_PROP_WRITE : 0) | - (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0); - - // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler. - common_hal_bleio_characteristic_construct( - characteristic, m_char_discovery_service, uuid, props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, - GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc - mp_obj_new_list(0, NULL)); - characteristic->handle = gattc_char->handle_value; - - mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic)); - } - - if (response->count > 0) { - m_discovery_successful = true; - } - m_discovery_in_process = false; -} - -STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, mp_obj_t device) { - for (size_t i = 0; i < response->count; ++i) { - ble_gattc_desc_t *gattc_desc = &response->descs[i]; - - // Remember handles for certain well-known descriptors. - switch (gattc_desc->uuid.uuid) { - case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG: - m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle; - break; - - case BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG: - m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle; - break; - - case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC: - m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle; - break; - - default: - // TODO: sd_ble_gattc_descriptors_discover() can return things that are not descriptors, - // so ignore those. - // https://devzone.nordicsemi.com/f/nordic-q-a/49500/sd_ble_gattc_descriptors_discover-is-returning-attributes-that-are-not-descriptors - break; - } - - bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t); - descriptor->base.type = &bleio_descriptor_type; - - bleio_uuid_obj_t *uuid = NULL; - - if (gattc_desc->uuid.type != BLE_UUID_TYPE_UNKNOWN) { - // Known descriptor UUID. - uuid = m_new_obj(bleio_uuid_obj_t); - uuid->base.type = &bleio_uuid_type; - bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_desc->uuid); - } else { - // The discovery response contained a 128-bit UUID that has not yet been registered with the - // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. - // For now, just leave the UUID as NULL. - } - - common_hal_bleio_descriptor_construct( - descriptor, m_desc_discovery_characteristic, uuid, - SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, - GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes); - descriptor->handle = gattc_desc->handle; - - mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor)); - } - - if (response->count > 0) { - m_discovery_successful = true; - } - m_discovery_in_process = false; -} - -STATIC void discovery_on_ble_evt(ble_evt_t *ble_evt, mp_obj_t device) { - switch (ble_evt->header.evt_id) { - case BLE_GAP_EVT_DISCONNECTED: - m_discovery_successful = false; - m_discovery_in_process = false; - break; - - case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: - on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, device); - break; - - case BLE_GATTC_EVT_CHAR_DISC_RSP: - on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, device); - break; - - case BLE_GATTC_EVT_DESC_DISC_RSP: - on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, device); - break; - - default: - // For debugging. - // mp_printf(&mp_plat_print, "Unhandled discovery event: 0x%04x\n", ble_evt->header.evt_id); - break; - } -} - - -void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist) { - mp_obj_list_t *remote_services_list = common_hal_bleio_device_get_remote_service_list(device); - - ble_drv_add_event_handler(discovery_on_ble_evt, device); - - // Start over with an empty list. - mp_obj_list_clear(MP_OBJ_FROM_PTR(common_hal_bleio_device_get_remote_service_list(device))); - - if (service_uuids_whitelist == mp_const_none) { - // List of service UUID's not given, so discover all available services. - - uint16_t next_service_start_handle = BLE_GATT_HANDLE_START; - - while (discover_next_services(device, next_service_start_handle, MP_OBJ_NULL)) { - // discover_next_services() appends to remote_services_list. - - // Get the most recently discovered service, and then ask for services - // whose handles start after the last attribute handle inside that service. - const bleio_service_obj_t *service = - MP_OBJ_TO_PTR(remote_services_list->items[remote_services_list->len - 1]); - next_service_start_handle = service->end_handle + 1; - } - } else { - mp_obj_iter_buf_t iter_buf; - mp_obj_t iterable = mp_getiter(service_uuids_whitelist, &iter_buf); - mp_obj_t uuid_obj; - while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { - mp_raise_ValueError(translate("non-UUID found in service_uuids_whitelist")); - } - bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj); - - ble_uuid_t nrf_uuid; - bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid); - - // Service might or might not be discovered; that's ok. Caller has to check - // Central.remote_services to find out. - // We only need to call this once for each service to discover. - discover_next_services(device, BLE_GATT_HANDLE_START, &nrf_uuid); - } - } - - - for (size_t service_idx = 0; service_idx < remote_services_list->len; ++service_idx) { - bleio_service_obj_t *service = MP_OBJ_TO_PTR(remote_services_list->items[service_idx]); - - // Skip the service if it had an unknown (unregistered) UUID. - if (service->uuid == NULL) { - continue; - } - - uint16_t next_char_start_handle = service->start_handle; - - // Stop when we go past the end of the range of handles for this service or - // discovery call returns nothing. - // discover_next_characteristics() appends to the characteristic_list. - while (next_char_start_handle <= service->end_handle && - discover_next_characteristics(device, service, next_char_start_handle)) { - - - // Get the most recently discovered characteristic, and then ask for characteristics - // whose handles start after the last attribute handle inside that characteristic. - const bleio_characteristic_obj_t *characteristic = - MP_OBJ_TO_PTR(service->characteristic_list->items[service->characteristic_list->len - 1]); - next_char_start_handle = characteristic->handle + 1; - } - - // Got characteristics for this service. Now discover descriptors for each characteristic. - size_t char_list_len = service->characteristic_list->len; - for (size_t char_idx = 0; char_idx < char_list_len; ++char_idx) { - bleio_characteristic_obj_t *characteristic = - MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx]); - const bool last_characteristic = char_idx == char_list_len - 1; - bleio_characteristic_obj_t *next_characteristic = last_characteristic - ? NULL - : MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx + 1]); - - // Skip the characteristic if it had an unknown (unregistered) UUID. - if (characteristic->uuid == NULL) { - continue; - } - - uint16_t next_desc_start_handle = characteristic->handle + 1; - - // Don't run past the end of this service or the beginning of the next characteristic. - uint16_t next_desc_end_handle = next_characteristic == NULL - ? service->end_handle - : next_characteristic->handle - 1; - - // Stop when we go past the end of the range of handles for this service or - // discovery call returns nothing. - // discover_next_descriptors() appends to the descriptor_list. - while (next_desc_start_handle <= service->end_handle && - next_desc_start_handle < next_desc_end_handle && - discover_next_descriptors(device, characteristic, - next_desc_start_handle, next_desc_end_handle)) { - - // Get the most recently discovered descriptor, and then ask for descriptors - // whose handles start after that descriptor's handle. - const bleio_descriptor_obj_t *descriptor = - MP_OBJ_TO_PTR(characteristic->descriptor_list->items[characteristic->descriptor_list->len - 1]); - next_desc_start_handle = descriptor->handle + 1; - } - } - } - - // This event handler is no longer needed. - ble_drv_remove_event_handler(discovery_on_ble_evt, device); - -} - // GATTS read of a Characteristic or Descriptor. -mp_obj_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle) { +size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len) { // conn_handle might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because // we can still read and write the local value. - mp_buffer_info_t bufinfo; ble_gatts_value_t gatts_value = { - .p_value = NULL, - .len = 0, + .p_value = buf, + .len = len, }; - // Read once to find out what size buffer we need, then read again to fill buffer. - - mp_obj_t value = mp_const_none; uint32_t err_code = sd_ble_gatts_value_get(conn_handle, handle, &gatts_value); - if (err_code == NRF_SUCCESS) { - value = mp_obj_new_bytearray_of_zeros(gatts_value.len); - mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_WRITE); - gatts_value.p_value = bufinfo.buf; - - // Read again, with the correct size of buffer. - err_code = sd_ble_gatts_value_get(conn_handle, handle, &gatts_value); - } - if (err_code != NRF_SUCCESS) { mp_raise_OSError_msg_varg(translate("Failed to read gatts value, err 0x%04x"), err_code); } - return value; + return gatts_value.len; } void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) { @@ -471,6 +122,72 @@ void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buff } } +typedef struct { + uint8_t* buf; + size_t len; + size_t final_len; + uint16_t conn_handle; + volatile uint16_t status; + volatile bool done; +} read_info_t; + +STATIC bool _on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { + read_info_t* read = param; + switch (ble_evt->header.evt_id) { + + // More events may be handled later, so keep this as a switch. + + case BLE_GATTC_EVT_READ_RSP: { + ble_gattc_evt_t* evt = &ble_evt->evt.gattc_evt; + ble_gattc_evt_read_rsp_t *response = &evt->params.read_rsp; + if (read && evt->conn_handle == read->conn_handle) { + read->status = evt->gatt_status; + size_t len = MIN(read->len, response->len); + memcpy(read->buf, response->data, len); + read->final_len = len; + // Indicate to busy-wait loop that we've read the attribute value. + read->done = true; + } + break; + } + + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id); + return false; + break; + } + return true; +} + +size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len) { + common_hal_bleio_check_connected(conn_handle); + + read_info_t read_info; + read_info.buf = buf; + read_info.len = len; + read_info.final_len = 0; + read_info.conn_handle = conn_handle; + // Set to true by the event handler. + read_info.done = false; + ble_drv_add_event_handler(_on_gattc_read_rsp_evt, &read_info); + + const uint32_t err_code = sd_ble_gattc_read(conn_handle, handle, 0); + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed initiate attribute read, err 0x%04x"), err_code); + } + + while (!read_info.done) { + RUN_BACKGROUND_TASKS; + } + if (read_info.status != BLE_GATT_STATUS_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), read_info.status); + } + + ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info); + return read_info.final_len; +} + void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) { common_hal_bleio_check_connected(conn_handle); @@ -500,3 +217,7 @@ void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buff } } + +void common_hal_bleio_gc_collect(void) { + bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj); +} diff --git a/ports/nrf/common-hal/_bleio/__init__.h b/ports/nrf/common-hal/_bleio/__init__.h index cf1a06945d..5fd2769f26 100644 --- a/ports/nrf/common-hal/_bleio/__init__.h +++ b/ports/nrf/common-hal/_bleio/__init__.h @@ -39,4 +39,9 @@ typedef struct { // 20 bytes max (23 - 3). #define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3) +const mp_obj_t base_error_messages[20]; + +// Track if the user code modified the BLE state to know if we need to undo it on reload. +bool vm_used_ble; + #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index b72d753904..211e853689 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -229,12 +229,10 @@ SRC_COMMON_HAL_ALL = \ _bleio/__init__.c \ _bleio/Adapter.c \ _bleio/Attribute.c \ - _bleio/Central.c \ _bleio/Characteristic.c \ _bleio/CharacteristicBuffer.c \ + _bleio/Connection.c \ _bleio/Descriptor.c \ - _bleio/Peripheral.c \ - _bleio/Scanner.c \ _bleio/Service.c \ _bleio/UUID.c \ analogio/AnalogIn.c \ @@ -307,6 +305,7 @@ SRC_SHARED_MODULE_ALL = \ _bleio/Address.c \ _bleio/Attribute.c \ _bleio/ScanEntry.c \ + _bleio/ScanResults.c \ _pixelbuf/PixelBuf.c \ _pixelbuf/__init__.c \ _stage/Layer.c \ diff --git a/py/ringbuf.h b/py/ringbuf.h index 5f82cc0968..7fc35d2661 100644 --- a/py/ringbuf.h +++ b/py/ringbuf.h @@ -99,4 +99,11 @@ static inline void ringbuf_put_n(ringbuf_t* r, uint8_t* buf, uint8_t bufsize) } } } + +static inline void ringbuf_get_n(ringbuf_t* r, uint8_t* buf, uint8_t bufsize) +{ + for(uint8_t i=0; i < bufsize; i++) { + buf[i] = ringbuf_get(r); + } +} #endif // MICROPY_INCLUDED_PY_RINGBUF_H diff --git a/py/vm.c b/py/vm.c index b5f53ee9a0..353fc88100 100644 --- a/py/vm.c +++ b/py/vm.c @@ -758,7 +758,7 @@ unwind_jump:; } else { PUSH(value); // push the next iteration value } - DISPATCH(); + DISPATCH_WITH_PEND_EXC_CHECK(); } // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index 0caca96b86..01dba04919 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -25,22 +25,45 @@ * THE SOFTWARE. */ +#include + #include "py/objproperty.h" +#include "py/runtime.h" #include "shared-bindings/_bleio/Address.h" #include "shared-bindings/_bleio/Adapter.h" +#define ADV_INTERVAL_MIN (0.0020f) +#define ADV_INTERVAL_MIN_STRING "0.0020" +#define ADV_INTERVAL_MAX (10.24f) +#define ADV_INTERVAL_MAX_STRING "10.24" +// 20ms is recommended by Apple +#define ADV_INTERVAL_DEFAULT (0.1f) + +#define INTERVAL_DEFAULT (0.1f) +#define INTERVAL_MIN (0.0025f) +#define INTERVAL_MIN_STRING "0.0025" +#define INTERVAL_MAX (40.959375f) +#define INTERVAL_MAX_STRING "40.959375" +#define WINDOW_DEFAULT (0.1f) + //| .. currentmodule:: _bleio //| -//| :class:`Adapter` --- BLE adapter information +//| :class:`Adapter` --- BLE adapter //| ---------------------------------------------------- //| -//| Get current status of the BLE adapter +//| The Adapter manages the discovery and connection to other nearby Bluetooth Low Energy devices. +//| This part of the Bluetooth Low Energy Specification is known as Generic Access Profile (GAP). //| -//| Usage:: +//| Discovery of other devices happens during a scanning process that listens for small packets of +//| information, known as advertisements, that are broadcast unencrypted. The advertising packets +//| have two different uses. The first is to broadcast a small piece of data to anyone who cares and +//| and nothing more. These are known as Beacons. The second class of advertisement is to promote +//| additional functionality available after the devices establish a connection. For example, a +//| BLE keyboard may advertise that it can provide key information, but not what the key info is. //| -//| import _bleio -//| _bleio.adapter.enabled = True -//| print(_bleio.adapter.address) +//| The built-in BLE adapter can do both parts of this process, it can scan for other device +//| advertisements and it can advertise it's own data. Furthermore, Adapters can accept incoming +//| connections and also initiate connections. //| //| .. class:: Adapter() @@ -49,19 +72,19 @@ //| Use `_bleio.adapter` to access the sole instance available. //| -//| .. attribute:: adapter.enabled +//| .. attribute:: enabled //| -//| State of the BLE adapter. +//| State of the BLE adapter. //| STATIC mp_obj_t bleio_adapter_get_enabled(mp_obj_t self) { - return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled()); + return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled(self)); } MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_enabled_obj, bleio_adapter_get_enabled); static mp_obj_t bleio_adapter_set_enabled(mp_obj_t self, mp_obj_t value) { const bool enabled = mp_obj_is_true(value); - common_hal_bleio_adapter_set_enabled(enabled); + common_hal_bleio_adapter_set_enabled(self, enabled); return mp_const_none; } @@ -74,12 +97,12 @@ const mp_obj_property_t bleio_adapter_enabled_obj = { (mp_obj_t)&mp_const_none_obj }, }; -//| .. attribute:: adapter.address +//| .. attribute:: address //| -//| MAC address of the BLE adapter. (read-only) +//| MAC address of the BLE adapter. (read-only) //| STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) { - return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_address()); + return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_address(self)); } MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_address_obj, bleio_adapter_get_address); @@ -91,29 +114,260 @@ const mp_obj_property_t bleio_adapter_address_obj = { (mp_obj_t)&mp_const_none_obj }, }; -//| .. attribute:: adapter.default_name +//| .. attribute:: name //| -//| default_name of the BLE adapter. (read-only) -//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``, -//| to make it easy to distinguish multiple CircuitPython boards. +//| name of the BLE adapter used once connected. Not used in advertisements. +//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``, +//| to make it easy to distinguish multiple CircuitPython boards. //| -STATIC mp_obj_t bleio_adapter_get_default_name(mp_obj_t self) { - return common_hal_bleio_adapter_get_default_name(); +STATIC mp_obj_t bleio_adapter_get_name(mp_obj_t self) { + return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_name(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_name_obj, bleio_adapter_get_name); + + +STATIC mp_obj_t bleio_adapter_set_name(mp_obj_t self, mp_obj_t new_name) { + common_hal_bleio_adapter_set_name(self, mp_obj_str_get_str(new_name)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(bleio_adapter_set_name_obj, bleio_adapter_set_name); + +const mp_obj_property_t bleio_adapter_name_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_adapter_get_name_obj, + (mp_obj_t)&bleio_adapter_set_name_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +//| .. method:: start_advertising(data, *, scan_response=None, connectable=True, interval=0.1) +//| +//| Starts advertising until `stop_advertising` is called or if connectable, another device +//| connects to us. +//| +//| :param buf data: advertising data packet bytes +//| :param buf scan_response: scan response data packet bytes. ``None`` if no scan response is needed. +//| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral. +//| :param float interval: advertising interval, in seconds +//| +STATIC mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_data, ARG_scan_response, ARG_connectable, ARG_interval }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_scan_response, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t data_bufinfo; + mp_get_buffer_raise(args[ARG_data].u_obj, &data_bufinfo, MP_BUFFER_READ); + + // Pass an empty buffer if scan_response not provided. + mp_buffer_info_t scan_response_bufinfo = { 0 }; + if (args[ARG_scan_response].u_obj != mp_const_none) { + mp_get_buffer_raise(args[ARG_scan_response].u_obj, &scan_response_bufinfo, MP_BUFFER_READ); + } + + if (args[ARG_interval].u_obj == MP_OBJ_NULL) { + args[ARG_interval].u_obj = mp_obj_new_float(ADV_INTERVAL_DEFAULT); + } + + const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj); + if (interval < ADV_INTERVAL_MIN || interval > ADV_INTERVAL_MAX) { + mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), + ADV_INTERVAL_MIN_STRING, ADV_INTERVAL_MAX_STRING); + } + + common_hal_bleio_adapter_start_advertising(self, args[ARG_connectable].u_bool, interval, + &data_bufinfo, &scan_response_bufinfo); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_advertising_obj, 2, bleio_adapter_start_advertising); + +//| .. method:: stop_advertising() +//| +//| Stop sending advertising packets. +STATIC mp_obj_t bleio_adapter_stop_advertising(mp_obj_t self_in) { + bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_adapter_stop_advertising(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_advertising_obj, bleio_adapter_stop_advertising); + +//| .. method:: start_scan(prefixes=b"", \*, buffer_size=512, extended=False, timeout=None, interval=0.1, window=0.1, minimum_rssi=-80) +//| +//| Starts a BLE scan and returns an iterator of results. Advertisements and scan responses are +//| filtered and returned separately. +//| +//| :param sequence prefixes: Sequence of byte string prefixes to filter advertising packets +//| with. A packets without an advertising structure that matches one of the prefixes are +//| ignored. Format is one byte for length (n) and n bytes of prefix and can be repeated. +//| :param int buffer_size: the maximum number of advertising bytes to buffer. +//| :param bool extended: When True, support extended advertising packets. Increasing buffer_size is recommended when this is set. +//| :param float timeout: the scan timeout in seconds. If None, will scan until `stop_scan` is called. +//| :param float interval: the interval (in seconds) between the start of two consecutive scan windows +//| Must be in the range 0.0025 - 40.959375 seconds. +//| :param float window: the duration (in seconds) to scan a single BLE channel. +//| window must be <= interval. +//| :param int minimum_rssi: the minimum rssi of entries to return. +//| :param bool active: retrieve scan responses for scannable advertisements. +//| :returns: an iterable of `_bleio.ScanEntry` objects +//| :rtype: iterable +//| +STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_prefixes, ARG_buffer_size, ARG_extended, ARG_timeout, ARG_interval, ARG_window, ARG_minimum_rssi, ARG_active }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_prefixes, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_buffer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 512} }, + { MP_QSTR_extended, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_window, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_minimum_rssi, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -80} }, + { MP_QSTR_active, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, + }; + + bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_float_t timeout = 0; + if (args[ARG_timeout].u_obj != MP_OBJ_NULL) { + timeout = mp_obj_get_float(args[ARG_timeout].u_obj); + } + + if (args[ARG_interval].u_obj == MP_OBJ_NULL) { + args[ARG_interval].u_obj = mp_obj_new_float(INTERVAL_DEFAULT); + } + + if (args[ARG_window].u_obj == MP_OBJ_NULL) { + args[ARG_window].u_obj = mp_obj_new_float(WINDOW_DEFAULT); + } + + const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj); + if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) { + mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), INTERVAL_MIN_STRING, INTERVAL_MAX_STRING); + } + + const mp_float_t window = mp_obj_float_get(args[ARG_window].u_obj); + if (window > interval) { + mp_raise_ValueError(translate("window must be <= interval")); + } + + mp_buffer_info_t prefix_bufinfo; + prefix_bufinfo.len = 0; + if (args[ARG_prefixes].u_obj != MP_OBJ_NULL) { + mp_get_buffer_raise(args[ARG_prefixes].u_obj, &prefix_bufinfo, MP_BUFFER_READ); + if (gc_nbytes(prefix_bufinfo.buf) == 0) { + mp_raise_ValueError(translate("Prefix buffer must be on the heap")); + } + } + + return common_hal_bleio_adapter_start_scan(self, prefix_bufinfo.buf, prefix_bufinfo.len, args[ARG_extended].u_bool, args[ARG_buffer_size].u_int, timeout, interval, window, args[ARG_minimum_rssi].u_int, args[ARG_active].u_bool); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_scan_obj, 1, bleio_adapter_start_scan); + +//| .. method:: stop_scan() +//| +//| Stop the current scan. +STATIC mp_obj_t bleio_adapter_stop_scan(mp_obj_t self_in) { + bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_adapter_stop_scan(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_scan_obj, bleio_adapter_stop_scan); + +//| .. attribute:: connected +//| +//| True when the adapter is connected to another device regardless of who initiated the +//| connection. (read-only) +//| +STATIC mp_obj_t bleio_adapter_get_connected(mp_obj_t self) { + return mp_obj_new_bool(common_hal_bleio_adapter_get_connected(self)); } -MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_default_name_obj, bleio_adapter_get_default_name); +MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_connected_obj, bleio_adapter_get_connected); -const mp_obj_property_t bleio_adapter_default_name_obj = { +const mp_obj_property_t bleio_adapter_connected_obj = { .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_adapter_get_default_name_obj, + .proxy = { (mp_obj_t)&bleio_adapter_get_connected_obj, (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: connections +//| +//| Tuple of active connections including those initiated through +//| :py:meth:`_bleio.Adapter.connect`. (read-only) +//| +STATIC mp_obj_t bleio_adapter_get_connections(mp_obj_t self) { + return common_hal_bleio_adapter_get_connections(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_connections_obj, bleio_adapter_get_connections); + +const mp_obj_property_t bleio_adapter_connections_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_adapter_get_connections_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +//| .. method:: connect(address, *, timeout, pair=False) +//| +//| Attempts a connection to the device with the given address. +//| +//| :param Address address: The address of the peripheral to connect to +//| :param float/int timeout: Try to connect for timeout seconds. +//| +STATIC mp_obj_t bleio_adapter_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_address, ARG_timeout, ARG_pair }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_pair, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (!MP_OBJ_IS_TYPE(args[ARG_address].u_obj, &bleio_address_type)) { + mp_raise_ValueError(translate("Expected an Address")); + } + + bleio_address_obj_t *address = MP_OBJ_TO_PTR(args[ARG_address].u_obj); + mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); + + return common_hal_bleio_adapter_connect(self, address, timeout, args[ARG_pair].u_bool); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_connect_obj, 2, bleio_adapter_connect); + + STATIC const mp_rom_map_elem_t bleio_adapter_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&bleio_adapter_enabled_obj) }, { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_adapter_address_obj) }, - { MP_ROM_QSTR(MP_QSTR_default_name), MP_ROM_PTR(&bleio_adapter_default_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_adapter_name_obj) }, + + { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_adapter_start_advertising_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_adapter_stop_advertising_obj) }, + + { MP_ROM_QSTR(MP_QSTR_start_scan), MP_ROM_PTR(&bleio_adapter_start_scan_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop_scan), MP_ROM_PTR(&bleio_adapter_stop_scan_obj) }, + + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_adapter_connect_obj) }, + + { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_adapter_connected_obj) }, + { MP_ROM_QSTR(MP_QSTR_connections), MP_ROM_PTR(&bleio_adapter_connections_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_adapter_locals_dict, bleio_adapter_locals_dict_table); diff --git a/shared-bindings/_bleio/Adapter.h b/shared-bindings/_bleio/Adapter.h index 932fc9c958..95d19cb319 100644 --- a/shared-bindings/_bleio/Adapter.h +++ b/shared-bindings/_bleio/Adapter.h @@ -28,13 +28,33 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H +#include + +#include "common-hal/_bleio/Adapter.h" + +#include "py/objstr.h" #include "shared-module/_bleio/Address.h" const mp_obj_type_t bleio_adapter_type; -extern bool common_hal_bleio_adapter_get_enabled(void); -extern void common_hal_bleio_adapter_set_enabled(bool enabled); -extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(void); -extern mp_obj_t common_hal_bleio_adapter_get_default_name(void); +extern bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self); +extern void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled); +extern bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self); +extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self); + +extern mp_obj_str_t* common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self); +extern void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* name); + +extern uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len); + +extern void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo); +void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self); + +mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, uint8_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active); +void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self); + +bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self); +mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self); +mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, bool pair); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H diff --git a/shared-bindings/_bleio/Address.c b/shared-bindings/_bleio/Address.c index cdee02b5d7..c31eb604b1 100644 --- a/shared-bindings/_bleio/Address.c +++ b/shared-bindings/_bleio/Address.c @@ -114,10 +114,11 @@ const mp_obj_property_t bleio_address_address_bytes_obj = { }; //| .. attribute:: type -//| +//| //| The address type (read-only). -//| One of the integer values: `PUBLIC`, `RANDOM_STATIC`, -//| `RANDOM_PRIVATE_RESOLVABLE`, or `RANDOM_PRIVATE_NON_RESOLVABLE`. +//| +//| One of the integer values: `PUBLIC`, `RANDOM_STATIC`, `RANDOM_PRIVATE_RESOLVABLE`, +//| or `RANDOM_PRIVATE_NON_RESOLVABLE`. //| STATIC mp_obj_t bleio_address_get_type(mp_obj_t self_in) { bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -159,6 +160,28 @@ STATIC mp_obj_t bleio_address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_o } } +//| .. method:: __hash__() +//| +//| Returns a hash for the Address data. +//| +STATIC mp_obj_t bleio_address_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + switch (op) { + // Two Addresses are equal if their address bytes and address_type are equal + case MP_UNARY_OP_HASH: { + mp_obj_t bytes = common_hal_bleio_address_get_address_bytes(MP_OBJ_TO_PTR(self_in)); + GET_STR_HASH(bytes, h); + if (h == 0) { + GET_STR_DATA_LEN(bytes, data, len); + h = qstr_compute_hash(data, len); + } + h ^= common_hal_bleio_address_get_type(MP_OBJ_TO_PTR(self_in)); + return MP_OBJ_NEW_SMALL_INT(h); + } + default: + return MP_OBJ_NULL; // op not supported + } +} + STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t buf_info; @@ -205,6 +228,7 @@ const mp_obj_type_t bleio_address_type = { .name = MP_QSTR_Address, .make_new = bleio_address_make_new, .print = bleio_address_print, + .unary_op = bleio_address_unary_op, .binary_op = bleio_address_binary_op, .locals_dict = (mp_obj_dict_t*)&bleio_address_locals_dict }; diff --git a/shared-bindings/_bleio/Central.c b/shared-bindings/_bleio/Central.c deleted file mode 100644 index 084f40cd62..0000000000 --- a/shared-bindings/_bleio/Central.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * Copyright (c) 2016 Glenn Ruben Bakke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "ble_drv.h" -#include "py/objarray.h" -#include "py/objproperty.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "shared-bindings/_bleio/Adapter.h" -#include "shared-bindings/_bleio/Address.h" -#include "shared-bindings/_bleio/Characteristic.h" -#include "shared-bindings/_bleio/Central.h" -#include "shared-bindings/_bleio/Service.h" - -//| .. currentmodule:: _bleio -//| -//| :class:`Central` -- A BLE central device -//| ========================================================= -//| -//| Implement a BLE central, which runs locally. Can connect to a given address. -//| -//| Usage:: -//| -//| import _bleio -//| -//| scanner = _bleio.Scanner() -//| entries = scanner.scan(2.5) -//| -//| my_entry = None -//| for entry in entries: -//| if entry.name is not None and entry.name == 'InterestingPeripheral': -//| my_entry = entry -//| break -//| -//| if not my_entry: -//| raise Exception("'InterestingPeripheral' not found") -//| -//| central = _bleio.Central() -//| central.connect(my_entry.address, 10) # timeout after 10 seconds -//| remote_services = central.discover_remote_services() -//| - -//| .. class:: Central() -//| -//| Create a new Central object. -//| -STATIC mp_obj_t bleio_central_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_arg_check_num(n_args, kw_args, 0, 0, false); - - bleio_central_obj_t *self = m_new_obj(bleio_central_obj_t); - self->base.type = &bleio_central_type; - - common_hal_bleio_central_construct(self); - - return MP_OBJ_FROM_PTR(self); -} - -//| .. method:: connect(address, timeout, *, service_uuids_whitelist=None) -//| Attempts a connection to the remote peripheral. -//| -//| :param Address address: The address of the peripheral to connect to -//| :param float/int timeout: Try to connect for timeout seconds. -//| -STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - enum { ARG_address, ARG_timeout, ARG_service_uuids_whitelist }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_timeout, MP_ARG_REQUIRED | MP_ARG_OBJ }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - if (!MP_OBJ_IS_TYPE(args[ARG_address].u_obj, &bleio_address_type)) { - mp_raise_ValueError(translate("Expected an Address")); - } - - bleio_address_obj_t *address = MP_OBJ_TO_PTR(args[ARG_address].u_obj); - mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); - - // common_hal_bleio_central_connect() will validate that services is an iterable or None. - common_hal_bleio_central_connect(self, address, timeout); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_central_connect_obj, 3, bleio_central_connect); - - -//| .. method:: disconnect() -//| -//| Disconnects from the remote peripheral. -//| -STATIC mp_obj_t bleio_central_disconnect(mp_obj_t self_in) { - bleio_central_obj_t *self = MP_OBJ_TO_PTR(self_in); - - common_hal_bleio_central_disconnect(self); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_disconnect_obj, bleio_central_disconnect); - -//| .. method:: discover_remote_services(service_uuids_whitelist=None) -//| Do BLE discovery for all services or for the given service UUIDS, -//| to find their handles and characteristics, and return the discovered services. -//| `Peripheral.connected` must be True. -//| -//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services -//| provided by the peripheral that you want to use. -//| The peripheral may provide more services, but services not listed are ignored -//| and will not be returned. -//| -//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow. -//| -//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you -//| you must have already created a :py:class:~`UUID` object for that UUID in order for the -//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered -//| for use. (This restriction may be lifted in the future.) -//| -//| :return: A tuple of services provided by the remote peripheral. -//| -STATIC mp_obj_t bleio_central_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - enum { ARG_service_uuids_whitelist }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_service_uuids_whitelist, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - if (!common_hal_bleio_central_get_connected(self)) { - mp_raise_ValueError(translate("Not connected")); - } - - return MP_OBJ_FROM_PTR(common_hal_bleio_central_discover_remote_services( - MP_OBJ_FROM_PTR(self), - args[ARG_service_uuids_whitelist].u_obj)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_central_discover_remote_services_obj, 1, bleio_central_discover_remote_services); - -//| .. attribute:: connected -//| -//| True if connected to a remove peripheral. -//| -STATIC mp_obj_t bleio_central_get_connected(mp_obj_t self_in) { - bleio_central_obj_t *self = MP_OBJ_TO_PTR(self_in); - - return mp_obj_new_bool(common_hal_bleio_central_get_connected(self)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_get_connected_obj, bleio_central_get_connected); - -const mp_obj_property_t bleio_central_connected_obj = { - .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_central_get_connected_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj }, -}; - -STATIC const mp_rom_map_elem_t bleio_central_locals_dict_table[] = { - // Methods - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_central_connect_obj) }, - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_central_disconnect_obj) }, - { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_central_discover_remote_services_obj) }, - - // Properties - { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_central_connected_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(bleio_central_locals_dict, bleio_central_locals_dict_table); - -const mp_obj_type_t bleio_central_type = { - { &mp_type_type }, - .name = MP_QSTR_Central, - .make_new = bleio_central_make_new, - .locals_dict = (mp_obj_dict_t*)&bleio_central_locals_dict -}; diff --git a/shared-bindings/_bleio/Central.h b/shared-bindings/_bleio/Central.h deleted file mode 100644 index 85d788654f..0000000000 --- a/shared-bindings/_bleio/Central.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H - -#include "py/objtuple.h" -#include "common-hal/_bleio/Central.h" -#include "common-hal/_bleio/Service.h" - -extern const mp_obj_type_t bleio_central_type; - -extern void common_hal_bleio_central_construct(bleio_central_obj_t *self); -extern void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout); -extern void common_hal_bleio_central_disconnect(bleio_central_obj_t *self); -extern bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self); -extern mp_obj_tuple_t *common_hal_bleio_central_discover_remote_services(bleio_central_obj_t *self, mp_obj_t service_uuids_whitelist); - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c index 1981555891..d89da2a2fa 100644 --- a/shared-bindings/_bleio/Characteristic.c +++ b/shared-bindings/_bleio/Characteristic.c @@ -45,8 +45,8 @@ //| //| There is no regular constructor for a Characteristic. A new local Characteristic can be created //| and attached to a Service by calling `add_to_service()`. -//| Remote Characteristic objects are created by `Central.discover_remote_services()` -//| or `Peripheral.discover_remote_services()` as part of remote Services. +//| Remote Characteristic objects are created by `Connection.discover_remote_services()` +//| as part of remote Services. //| //| .. method:: add_to_service(service, uuid, *, properties=0, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=None) @@ -134,12 +134,10 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ // Range checking on max_length arg is done by the common_hal layer, because // it may vary depending on underlying BLE implementation. common_hal_bleio_characteristic_construct( - characteristic, MP_OBJ_TO_PTR(service_obj), MP_OBJ_TO_PTR(uuid_obj), + characteristic, MP_OBJ_TO_PTR(service_obj), 0, MP_OBJ_TO_PTR(uuid_obj), properties, read_perm, write_perm, max_length, fixed_length, &initial_value_bufinfo); - common_hal_bleio_service_add_characteristic(service_obj, characteristic); - return MP_OBJ_FROM_PTR(characteristic); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_add_to_service_fun_obj, 3, bleio_characteristic_add_to_service); @@ -170,7 +168,8 @@ const mp_obj_property_t bleio_characteristic_properties_obj = { //| .. attribute:: uuid //| //| The UUID of this characteristic. (read-only) -//| Will be ``None`` if the 128-bit UUID for this characteristic is not known. +//| +//| Will be ``None`` if the 128-bit UUID for this characteristic is not known. //| STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -194,7 +193,9 @@ const mp_obj_property_t bleio_characteristic_uuid_obj = { STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - return common_hal_bleio_characteristic_get_value(self); + uint8_t temp[512]; + size_t actual_len = common_hal_bleio_characteristic_get_value(self, temp, sizeof(temp)); + return mp_obj_new_bytearray(actual_len, temp); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_value_obj, bleio_characteristic_get_value); @@ -224,8 +225,20 @@ const mp_obj_property_t bleio_characteristic_value_obj = { STATIC mp_obj_t bleio_characteristic_get_descriptors(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); // Return list as a tuple so user won't be able to change it. - mp_obj_list_t *char_list = common_hal_bleio_characteristic_get_descriptor_list(self); - return mp_obj_new_tuple(char_list->len, char_list->items); + bleio_descriptor_obj_t *descriptors = common_hal_bleio_characteristic_get_descriptor_list(self); + bleio_descriptor_obj_t *head = descriptors; + size_t len = 0; + while (head != NULL) { + len++; + head = head->next; + } + mp_obj_tuple_t * t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL)); + head = descriptors; + for (size_t i = len - 1; i >= 0; i--) { + t->items[i] = MP_OBJ_FROM_PTR(head); + head = head->next; + } + return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_descriptors_obj, bleio_characteristic_get_descriptors); @@ -282,7 +295,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_set_cccd_obj, 1, bleio_ch STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_add_to_service), MP_ROM_PTR(&bleio_characteristic_add_to_service_obj) }, - { MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_get_properties_obj) }, + { MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_properties_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_characteristic_uuid_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_characteristic_value_obj) }, { MP_ROM_QSTR(MP_QSTR_set_cccd), MP_ROM_PTR(&bleio_characteristic_set_cccd_obj) }, diff --git a/shared-bindings/_bleio/Characteristic.h b/shared-bindings/_bleio/Characteristic.h index a816c60506..c4356fd4b9 100644 --- a/shared-bindings/_bleio/Characteristic.h +++ b/shared-bindings/_bleio/Characteristic.h @@ -36,12 +36,12 @@ extern const mp_obj_type_t bleio_characteristic_type; -extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo); -extern mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self); +extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo); +extern size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len); extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo); extern bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self); extern bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self); -extern mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self); +extern bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self); extern bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self); extern void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor); extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate); diff --git a/shared-bindings/_bleio/Connection.c b/shared-bindings/_bleio/Connection.c new file mode 100644 index 0000000000..1c6931b29d --- /dev/null +++ b/shared-bindings/_bleio/Connection.c @@ -0,0 +1,171 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2016 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/_bleio/Connection.h" + +#include +#include + +#include "ble_drv.h" +#include "py/objarray.h" +#include "py/objproperty.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "shared-bindings/_bleio/Address.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Service.h" + +//| .. currentmodule:: _bleio +//| +//| :class:`Connection` -- A BLE connection +//| ========================================================= +//| +//| A BLE connection to another device. Used to discover and interact with services on the other +//| device. +//| +//| Usage:: +//| +//| import _bleio +//| +//| my_entry = None +//| for entry in _bleio.adapter.scan(2.5): +//| if entry.name is not None and entry.name == 'InterestingPeripheral': +//| my_entry = entry +//| break +//| +//| if not my_entry: +//| raise Exception("'InterestingPeripheral' not found") +//| +//| connection = _bleio.adapter.connect(my_entry.address, timeout=10) +//| + +STATIC void ensure_connected(bleio_connection_obj_t *self) { + if (!common_hal_bleio_connection_get_connected(self)) { + mp_raise_ValueError(translate("Connection has been disconnected and can no longer be used. Create a new connection.")); + } +} + +//| .. class:: Connection() +//| +//| Connections cannot be made directly. Instead, to initiate a connection use `Adapter.connect`. +//| Connections may also be made when another device initiates a connection. To use a Connection +//| created by a peer, read the `Adapter.connections` property. +//| +//| .. method:: disconnect() +//| +//| Disconnects from the remote peripheral. +//| +STATIC mp_obj_t bleio_connection_disconnect(mp_obj_t self_in) { + bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in); + ensure_connected(self); + + common_hal_bleio_connection_disconnect(self->connection); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_disconnect_obj, bleio_connection_disconnect); + +//| .. method:: discover_remote_services(service_uuids_whitelist=None) +//| +//| Do BLE discovery for all services or for the given service UUIDS, +//| to find their handles and characteristics, and return the discovered services. +//| `Connection.connected` must be True. +//| +//| :param iterable service_uuids_whitelist: +//| +//| an iterable of :py:class:~`UUID` objects for the services provided by the peripheral +//| that you want to use. +//| +//| The peripheral may provide more services, but services not listed are ignored +//| and will not be returned. +//| +//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be +//| slow. +//| +//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you +//| you must have already created a :py:class:~`UUID` object for that UUID in order for the +//| service or characteristic to be discovered. Creating the UUID causes the UUID to be +//| registered for use. (This restriction may be lifted in the future.) +//| +//| :return: A tuple of `_bleio.Service` objects provided by the remote peripheral. +//| +STATIC mp_obj_t bleio_connection_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_connection_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_service_uuids_whitelist }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_service_uuids_whitelist, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + ensure_connected(self); + + return MP_OBJ_FROM_PTR(common_hal_bleio_connection_discover_remote_services( + self, + args[ARG_service_uuids_whitelist].u_obj)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_connection_discover_remote_services_obj, 1, bleio_connection_discover_remote_services); + +//| .. attribute:: connected +//| +//| True if connected to a remote peer. +//| +STATIC mp_obj_t bleio_connection_get_connected(mp_obj_t self_in) { + bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(common_hal_bleio_connection_get_connected(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_get_connected_obj, bleio_connection_get_connected); + +const mp_obj_property_t bleio_connection_connected_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_connection_get_connected_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_connection_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_connection_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_connection_discover_remote_services_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_connection_connected_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_connection_locals_dict, bleio_connection_locals_dict_table); + +const mp_obj_type_t bleio_connection_type = { + { &mp_type_type }, + .name = MP_QSTR_Connection, + .locals_dict = (mp_obj_dict_t*)&bleio_connection_locals_dict, + .unary_op = mp_generic_unary_op, +}; diff --git a/shared-bindings/_bleio/Scanner.h b/shared-bindings/_bleio/Connection.h similarity index 66% rename from shared-bindings/_bleio/Scanner.h rename to shared-bindings/_bleio/Connection.h index cbaa778662..5de6730c99 100644 --- a/shared-bindings/_bleio/Scanner.h +++ b/shared-bindings/_bleio/Connection.h @@ -25,16 +25,17 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CONNECTION_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CONNECTION_H -#include "py/objtype.h" -#include "common-hal/_bleio/Scanner.h" +#include "py/objtuple.h" +#include "common-hal/_bleio/Connection.h" +#include "common-hal/_bleio/Service.h" -extern const mp_obj_type_t bleio_scanner_type; +extern const mp_obj_type_t bleio_connection_type; -extern void common_hal_bleio_scanner_construct(bleio_scanner_obj_t *self); -extern mp_obj_t common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_float_t timeout, mp_float_t interval, mp_float_t window); -extern void common_hal_bleio_scanner_stop(bleio_scanner_obj_t *self); +extern void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self); +extern bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self); +extern mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist); -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CONNECTION_H diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c index 0ab9fe8e9e..45a95903e1 100644 --- a/shared-bindings/_bleio/Descriptor.c +++ b/shared-bindings/_bleio/Descriptor.c @@ -46,9 +46,8 @@ //| //| There is no regular constructor for a Descriptor. A new local Descriptor can be created //| and attached to a Characteristic by calling `add_to_characteristic()`. -//| Remote Descriptor objects are created by `Central.discover_remote_services()` -//| or `Peripheral.discover_remote_services()` as part of remote Characteristics -//| in the remote Services that are discovered. +//| Remote Descriptor objects are created by `Connection.discover_remote_services()` +//| as part of remote Characteristics in the remote Services that are discovered. //| //| .. classmethod:: add_to_characteristic(characteristic, uuid, *, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=b'') //| @@ -180,7 +179,9 @@ const mp_obj_property_t bleio_descriptor_characteristic_obj = { STATIC mp_obj_t bleio_descriptor_get_value(mp_obj_t self_in) { bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); - return common_hal_bleio_descriptor_get_value(self); + uint8_t temp[512]; + size_t actual_len = common_hal_bleio_descriptor_get_value(self, temp, sizeof(temp)); + return mp_obj_new_bytearray(actual_len, temp); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_value_obj, bleio_descriptor_get_value); diff --git a/shared-bindings/_bleio/Descriptor.h b/shared-bindings/_bleio/Descriptor.h index 7544bdb17b..273cb1c1e3 100644 --- a/shared-bindings/_bleio/Descriptor.h +++ b/shared-bindings/_bleio/Descriptor.h @@ -38,7 +38,7 @@ extern const mp_obj_type_t bleio_descriptor_type; extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo); extern bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self); extern bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self); -extern mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self); +extern size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t* buf, size_t len); extern void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H diff --git a/shared-bindings/_bleio/Peripheral.c b/shared-bindings/_bleio/Peripheral.c deleted file mode 100644 index 0bf2927442..0000000000 --- a/shared-bindings/_bleio/Peripheral.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * Copyright (c) 2016 Glenn Ruben Bakke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "ble_drv.h" -#include "py/objarray.h" -#include "py/objproperty.h" -#include "py/objstr.h" -#include "py/runtime.h" - -#include "shared-bindings/_bleio/Adapter.h" -#include "shared-bindings/_bleio/Characteristic.h" -#include "shared-bindings/_bleio/Peripheral.h" -#include "shared-bindings/_bleio/Service.h" -#include "shared-bindings/_bleio/UUID.h" -#include "shared-module/_bleio/ScanEntry.h" - -#include "common-hal/_bleio/Peripheral.h" - -#define ADV_INTERVAL_MIN (0.0020f) -#define ADV_INTERVAL_MIN_STRING "0.0020" -#define ADV_INTERVAL_MAX (10.24f) -#define ADV_INTERVAL_MAX_STRING "10.24" -// 20ms is recommended by Apple -#define ADV_INTERVAL_DEFAULT (0.1f) - -//| .. currentmodule:: _bleio -//| -//| :class:`Peripheral` -- A BLE peripheral device -//| ========================================================= -//| -//| Implement a BLE peripheral which runs locally. -//| Set up using the supplied services, and then allow advertising to be started and stopped. -//| -//| Usage:: -//| -//| from _bleio import Characteristic, Peripheral, Service -//| from adafruit_ble.advertising import ServerAdvertisement -//| -//| # Create a peripheral and start it up. -//| peripheral = _bleio.Peripheral() -//| -//| # Create a Service and add it to this Peripheral. -//| service = Service.add_to_peripheral(peripheral, _bleio.UUID(0x180f)) -//| -//| # Create a Characteristic and add it to the Service. -//| characteristic = Characteristic.add_to_service(service, -//| _bleio.UUID(0x2919), properties=Characteristic.READ | Characteristic.NOTIFY) -//| -//| adv = ServerAdvertisement(peripheral) -//| peripheral.start_advertising(adv.advertising_data_bytes, scan_response=adv.scan_response_bytes) -//| -//| while not peripheral.connected: -//| # Wait for connection. -//| pass -//| -//| .. class:: Peripheral(name=None) -//| -//| Create a new Peripheral object. -//| -//| :param str name: The name used when advertising this peripheral. If name is None, -//| _bleio.adapter.default_name will be used. -//| -STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_name }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_name, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - bleio_peripheral_obj_t *self = m_new_obj(bleio_peripheral_obj_t); - self->base.type = &bleio_peripheral_type; - - mp_obj_t name = args[ARG_name].u_obj; - if (name == mp_const_none) { - name = common_hal_bleio_adapter_get_default_name(); - } else if (!MP_OBJ_IS_STR(name)) { - mp_raise_ValueError(translate("name must be a string")); - } - - common_hal_bleio_peripheral_construct(self, name); - - return MP_OBJ_FROM_PTR(self); -} - -//| .. attribute:: connected (read-only) -//| -//| True if connected to a BLE Central device. -//| -STATIC mp_obj_t bleio_peripheral_get_connected(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - return mp_obj_new_bool(common_hal_bleio_peripheral_get_connected(self)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_connected_obj, bleio_peripheral_get_connected); - -const mp_obj_property_t bleio_peripheral_connected_obj = { - .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_peripheral_get_connected_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj }, -}; - -//| .. attribute:: services -//| -//| A tuple of :py:class:`Service` objects offered by this peripheral. (read-only) -//| -STATIC mp_obj_t bleio_peripheral_get_services(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - // Return list as a tuple so user won't be able to change it. - mp_obj_list_t *services_list = common_hal_bleio_peripheral_get_services(self); - return mp_obj_new_tuple(services_list->len, services_list->items); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_services_obj, bleio_peripheral_get_services); - -const mp_obj_property_t bleio_peripheral_services_obj = { - .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_peripheral_get_services_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj }, -}; - -//| .. attribute:: name -//| -//| The peripheral's name, included when advertising. (read-only) -//| -STATIC mp_obj_t bleio_peripheral_get_name(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - return common_hal_bleio_peripheral_get_name(self); -} -MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_name_obj, bleio_peripheral_get_name); - -const mp_obj_property_t bleio_peripheral_name_obj = { - .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_peripheral_get_name_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj }, -}; - -//| .. method:: start_advertising(data, *, scan_response=None, connectable=True, interval=0.1) -//| -//| Starts advertising the peripheral. The peripheral's name and -//| services are included in the advertisement packets. -//| -//| :param buf data: advertising data packet bytes -//| :param buf scan_response: scan response data packet bytes. ``None`` if no scan response is needed. -//| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral. -//| :param float interval: advertising interval, in seconds -//| -STATIC mp_obj_t bleio_peripheral_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - enum { ARG_data, ARG_scan_response, ARG_connectable, ARG_interval }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_scan_response, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, - { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - mp_buffer_info_t data_bufinfo; - mp_get_buffer_raise(args[ARG_data].u_obj, &data_bufinfo, MP_BUFFER_READ); - - // Pass an empty buffer if scan_response not provided. - mp_buffer_info_t scan_response_bufinfo = { 0 }; - if (args[ARG_scan_response].u_obj != mp_const_none) { - mp_get_buffer_raise(args[ARG_scan_response].u_obj, &scan_response_bufinfo, MP_BUFFER_READ); - } - - if (args[ARG_interval].u_obj == MP_OBJ_NULL) { - args[ARG_interval].u_obj = mp_obj_new_float(ADV_INTERVAL_DEFAULT); - } - - const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj); - if (interval < ADV_INTERVAL_MIN || interval > ADV_INTERVAL_MAX) { - mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), - ADV_INTERVAL_MIN_STRING, ADV_INTERVAL_MAX_STRING); - } - - common_hal_bleio_peripheral_start_advertising(self, args[ARG_connectable].u_bool, interval, - &data_bufinfo, &scan_response_bufinfo); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_start_advertising_obj, 2, bleio_peripheral_start_advertising); - -//| .. method:: stop_advertising() -//| -//| Stop sending advertising packets. -STATIC mp_obj_t bleio_peripheral_stop_advertising(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - common_hal_bleio_peripheral_stop_advertising(self); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_stop_advertising_obj, bleio_peripheral_stop_advertising); - -//| .. method:: disconnect() -//| -//| Disconnects from the remote central. -//| Normally the central initiates a disconnection. Use this only -//| if necessary for your application. -//| -STATIC mp_obj_t bleio_peripheral_disconnect(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - common_hal_bleio_peripheral_disconnect(self); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_disconnect_obj, bleio_peripheral_disconnect); - -//| .. method:: discover_remote_services(service_uuids_whitelist=None) -//| Do BLE discovery for all services or for the given service UUIDS, -//| to find their handles and characteristics, and return the discovered services. -//| `Peripheral.connected` must be True. -//| -//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services -//| provided by the peripheral that you want to use. -//| The peripheral may provide more services, but services not listed are ignored -//| and will not be returned. -//| -//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow. -//| -//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you -//| you must have already created a :py:class:~`UUID` object for that UUID in order for the -//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered -//| for use. (This restriction may be lifted in the future.) -//| -//| Thought it is unusual for a peripheral to act as a BLE client, it can do so, and -//| needs to be able to do discovery on its peer (a central). -//| Examples include a peripheral accessing a central that provides Current Time Service, -//| Apple Notification Center Service, or Battery Service. -//| -//| :return: A tuple of services provided by the remote central. -//| -STATIC mp_obj_t bleio_peripheral_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - enum { ARG_service_uuids_whitelist }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_service_uuids_whitelist, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - if (!common_hal_bleio_peripheral_get_connected(self)) { - mp_raise_ValueError(translate("Not connected")); - } - - return MP_OBJ_FROM_PTR(common_hal_bleio_peripheral_discover_remote_services( - MP_OBJ_FROM_PTR(self), - args[ARG_service_uuids_whitelist].u_obj)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_discover_remote_services_obj, 1, bleio_peripheral_discover_remote_services); - -//| .. method:: pair() -//| -//| Request pairing with connected central. -STATIC mp_obj_t bleio_peripheral_pair(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - common_hal_bleio_peripheral_pair(self); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_pair_obj, bleio_peripheral_pair); - -STATIC const mp_rom_map_elem_t bleio_peripheral_locals_dict_table[] = { - // Methods - { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_peripheral_stop_advertising_obj) }, - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) }, - { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_peripheral_discover_remote_services_obj) }, - { MP_ROM_QSTR(MP_QSTR_pair), MP_ROM_PTR(&bleio_peripheral_pair_obj) }, - - // Properties - { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) }, - { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) }, - { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(bleio_peripheral_locals_dict, bleio_peripheral_locals_dict_table); - -const mp_obj_type_t bleio_peripheral_type = { - { &mp_type_type }, - .name = MP_QSTR_Peripheral, - .make_new = bleio_peripheral_make_new, - .locals_dict = (mp_obj_dict_t*)&bleio_peripheral_locals_dict -}; diff --git a/shared-bindings/_bleio/Peripheral.h b/shared-bindings/_bleio/Peripheral.h deleted file mode 100644 index bc56a93389..0000000000 --- a/shared-bindings/_bleio/Peripheral.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H - -#include "py/objtuple.h" -#include "common-hal/_bleio/Peripheral.h" -#include "common-hal/_bleio/Service.h" - -extern const mp_obj_type_t bleio_peripheral_type; - -extern void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_t name); -extern void common_hal_bleio_peripheral_add_service(bleio_peripheral_obj_t *self, bleio_service_obj_t *service); -extern mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self); -extern bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self); -extern mp_obj_t common_hal_bleio_peripheral_get_name(bleio_peripheral_obj_t *self); -extern void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *device, bool connectable, float interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo); -extern void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *device); -extern void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *device); -extern mp_obj_tuple_t *common_hal_bleio_peripheral_discover_remote_services(bleio_peripheral_obj_t *self, mp_obj_t service_uuids_whitelist); -extern void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *device); - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H diff --git a/shared-bindings/_bleio/ScanEntry.c b/shared-bindings/_bleio/ScanEntry.c index bec380d03f..d03cd6fb55 100644 --- a/shared-bindings/_bleio/ScanEntry.c +++ b/shared-bindings/_bleio/ScanEntry.c @@ -29,6 +29,7 @@ #include #include "py/objproperty.h" +#include "py/runtime.h" #include "shared-bindings/_bleio/Address.h" #include "shared-bindings/_bleio/ScanEntry.h" #include "shared-bindings/_bleio/UUID.h" @@ -36,14 +37,43 @@ //| .. currentmodule:: _bleio //| -//| :class:`ScanEntry` -- BLE scan response entry +//| :class:`ScanEntry` -- BLE scan data //| ========================================================= //| -//| Encapsulates information about a device that was received as a -//| response to a BLE scan request. This object may only be created -//| by a `_bleio.Scanner`: it has no user-visible constructor. +//| Encapsulates information about a device that was received during scanning. It can be +//| advertisement or scan response data. This object may only be created by a `_bleio.ScanResults`: +//| it has no user-visible constructor. //| +//| .. class:: ScanEntry() +//| +//| Cannot be instantiated directly. Use `_bleio.Adapter.start_scan`. +//| +//| .. method:: matches(prefixes, *, all=True) +//| +//| Returns True if the ScanEntry matches all prefixes when ``all`` is True. This is stricter +//| than the scan filtering which accepts any advertisements that match any of the prefixes +//| where all is False. +//| +STATIC mp_obj_t bleio_scanentry_matches(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_prefixes, ARG_all }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_prefixes, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_all, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_prefixes].u_obj, &bufinfo, MP_BUFFER_READ); + return mp_obj_new_bool(common_hal_bleio_scanentry_matches(self, bufinfo.buf, bufinfo.len, args[ARG_all].u_bool)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_scanentry_matches_obj, 2, bleio_scanentry_matches); + //| .. attribute:: address //| //| The address of the device (read-only), of type `_bleio.Address`. @@ -95,11 +125,47 @@ const mp_obj_property_t bleio_scanentry_rssi_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: connectable +//| +//| True if the device can be connected to. (read-only) +//| +STATIC mp_obj_t scanentry_get_connectable(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bool(common_hal_bleio_scanentry_get_connectable(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanentry_get_connectable_obj, scanentry_get_connectable); + +const mp_obj_property_t bleio_scanentry_connectable_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_scanentry_get_connectable_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +//| .. attribute:: scan_response +//| +//| True if the entry was a scan response. (read-only) +//| +STATIC mp_obj_t scanentry_get_scan_response(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bool(common_hal_bleio_scanentry_get_scan_response(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanentry_get_scan_response_obj, scanentry_get_scan_response); + +const mp_obj_property_t bleio_scanentry_scan_response_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_scanentry_get_scan_response_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; STATIC const mp_rom_map_elem_t bleio_scanentry_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_scanentry_address_obj) }, { MP_ROM_QSTR(MP_QSTR_advertisement_bytes), MP_ROM_PTR(&bleio_scanentry_advertisement_bytes_obj) }, { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&bleio_scanentry_rssi_obj) }, + { MP_ROM_QSTR(MP_QSTR_connectable), MP_ROM_PTR(&bleio_scanentry_connectable_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan_response), MP_ROM_PTR(&bleio_scanentry_scan_response_obj) }, + { MP_ROM_QSTR(MP_QSTR_matches), MP_ROM_PTR(&bleio_scanentry_matches_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_scanentry_locals_dict, bleio_scanentry_locals_dict_table); diff --git a/shared-bindings/_bleio/ScanEntry.h b/shared-bindings/_bleio/ScanEntry.h index 8af1f050a8..9aeaf20d33 100644 --- a/shared-bindings/_bleio/ScanEntry.h +++ b/shared-bindings/_bleio/ScanEntry.h @@ -37,5 +37,8 @@ extern const mp_obj_type_t bleio_scanentry_type; mp_obj_t common_hal_bleio_scanentry_get_address(bleio_scanentry_obj_t *self); mp_obj_t common_hal_bleio_scanentry_get_advertisement_bytes(bleio_scanentry_obj_t *self); mp_int_t common_hal_bleio_scanentry_get_rssi(bleio_scanentry_obj_t *self); +bool common_hal_bleio_scanentry_get_connectable(bleio_scanentry_obj_t *self); +bool common_hal_bleio_scanentry_get_scan_response(bleio_scanentry_obj_t *self); +bool common_hal_bleio_scanentry_matches(bleio_scanentry_obj_t *self, uint8_t* prefixes, size_t prefixes_len, bool all); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H diff --git a/shared-bindings/_bleio/ScanResults.c b/shared-bindings/_bleio/ScanResults.c new file mode 100644 index 0000000000..dcece3d5d4 --- /dev/null +++ b/shared-bindings/_bleio/ScanResults.c @@ -0,0 +1,72 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2017 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/_bleio/ScanResults.h" + +//| .. currentmodule:: _bleio +//| +//| :class:`ScanResults` -- An Iterator over BLE scanning results +//| =============================================================== +//| +//| Iterates over advertising data received while scanning. This object is always created +//| by a `_bleio.Adapter`: it has no user-visible constructor. +//| +STATIC mp_obj_t scanresults_iternext(mp_obj_t self_in) { + mp_check_self(MP_OBJ_IS_TYPE(self_in, &bleio_scanresults_type)); + bleio_scanresults_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_t scan_entry = common_hal_bleio_scanresults_next(self); + if (scan_entry != mp_const_none) { + return scan_entry; + } + return MP_OBJ_STOP_ITERATION; +} + +//| .. class:: ScanResults() +//| +//| Cannot be instantiated directly. Use `_bleio.Adapter.start_scan`. +//| +//| .. method:: __iter__() +//| +//| Returns itself since it is the iterator. +//| +//| .. method:: __next__() +//| +//| Returns the next `_bleio.ScanEntry`. Blocks if none have been received and scanning is still +//| active. Raises `StopIteration` if scanning is finished and no other results are available. +//| + +const mp_obj_type_t bleio_scanresults_type = { + { &mp_type_type }, + .name = MP_QSTR_ScanResults, + .getiter = mp_identity_getiter, + .iternext = scanresults_iternext, +}; diff --git a/ports/nrf/common-hal/_bleio/Scanner.h b/shared-bindings/_bleio/ScanResults.h similarity index 76% rename from ports/nrf/common-hal/_bleio/Scanner.h rename to shared-bindings/_bleio/ScanResults.h index 3768a52cb8..a8c88c215d 100644 --- a/ports/nrf/common-hal/_bleio/Scanner.h +++ b/shared-bindings/_bleio/ScanResults.h @@ -5,6 +5,7 @@ * * Copyright (c) 2019 Dan Halbert for Adafruit Industries * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,16 +26,14 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SCANNER_H -#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SCANNER_H +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANRESULTS_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANRESULTS_H #include "py/obj.h" +#include "shared-module/_bleio/ScanResults.h" -typedef struct { - mp_obj_base_t base; - mp_obj_t scan_entries; - uint16_t interval; - uint16_t window; -} bleio_scanner_obj_t; +extern const mp_obj_type_t bleio_scanresults_type; -#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SCANNER_H +mp_obj_t common_hal_bleio_scanresults_next(bleio_scanresults_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANRESULTS_H diff --git a/shared-bindings/_bleio/Scanner.c b/shared-bindings/_bleio/Scanner.c deleted file mode 100644 index 94cec97529..0000000000 --- a/shared-bindings/_bleio/Scanner.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "py/objproperty.h" -#include "py/runtime.h" -#include "shared-bindings/_bleio/ScanEntry.h" -#include "shared-bindings/_bleio/Scanner.h" - -#define INTERVAL_DEFAULT (0.1f) -#define INTERVAL_MIN (0.0025f) -#define INTERVAL_MIN_STRING "0.0025" -#define INTERVAL_MAX (40.959375f) -#define INTERVAL_MAX_STRING "40.959375" -#define WINDOW_DEFAULT (0.1f) - -//| .. currentmodule:: _bleio -//| -//| :class:`Scanner` -- scan for nearby BLE devices -//| ========================================================= -//| -//| Scan for nearby BLE devices. -//| -//| Usage:: -//| -//| import _bleio -//| scanner = _bleio.Scanner() -//| entries = scanner.scan(2.5) # Scan for 2.5 seconds -//| - -//| .. class:: Scanner() -//| -//| Create a new Scanner object. -//| -STATIC mp_obj_t bleio_scanner_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *all_args, mp_map_t *kw_args) { - mp_arg_check_num(n_args, kw_args, 0, 0, false); - - bleio_scanner_obj_t *self = m_new_obj(bleio_scanner_obj_t); - self->base.type = type; - - common_hal_bleio_scanner_construct(self); - - return MP_OBJ_FROM_PTR(self); -} - -//| .. method:: scan(timeout, \*, interval=0.1, window=0.1) -//| -//| Performs a BLE scan. -//| -//| :param float timeout: the scan timeout in seconds -//| :param float interval: the interval (in seconds) between the start of two consecutive scan windows -//| Must be in the range 0.0025 - 40.959375 seconds. -//| :param float window: the duration (in seconds) to scan a single BLE channel. -//| window must be <= interval. -//| :returns: an iterable of `ScanEntry` objects -//| :rtype: iterable -//| -STATIC mp_obj_t bleio_scanner_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_timeout, ARG_interval, ARG_window }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_timeout, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_window, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - }; - - bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - const mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); - - if (args[ARG_interval].u_obj == MP_OBJ_NULL) { - args[ARG_interval].u_obj = mp_obj_new_float(INTERVAL_DEFAULT); - } - - if (args[ARG_window].u_obj == MP_OBJ_NULL) { - args[ARG_window].u_obj = mp_obj_new_float(WINDOW_DEFAULT); - } - - const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj); - if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) { - mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), INTERVAL_MIN_STRING, INTERVAL_MAX_STRING); - } - - const mp_float_t window = mp_obj_float_get(args[ARG_window].u_obj); - if (window > interval) { - mp_raise_ValueError(translate("window must be <= interval")); - } - - return common_hal_bleio_scanner_scan(self, timeout, interval, window); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_scanner_scan_obj, 2, bleio_scanner_scan); - - -STATIC const mp_rom_map_elem_t bleio_scanner_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&bleio_scanner_scan_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(bleio_scanner_locals_dict, bleio_scanner_locals_dict_table); - -const mp_obj_type_t bleio_scanner_type = { - { &mp_type_type }, - .name = MP_QSTR_Scanner, - .make_new = bleio_scanner_make_new, - .locals_dict = (mp_obj_dict_t*)&bleio_scanner_locals_dict -}; diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c index da5633f2a3..68605cec00 100644 --- a/shared-bindings/_bleio/Service.c +++ b/shared-bindings/_bleio/Service.c @@ -29,54 +29,38 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/_bleio/Characteristic.h" -#include "shared-bindings/_bleio/Peripheral.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" //| .. currentmodule:: _bleio //| -//| :class:`Service` -- BLE service +//| :class:`Service` -- BLE GATT Service //| ========================================================= //| //| Stores information about a BLE service and its characteristics. //| -//| .. class:: Service +//| .. class:: Service(uuid, *, secondary=False) //| -//| There is no regular constructor for a Service. A new local Service can be created -//| and attached to a Peripheral by calling `add_to_peripheral()`. -//| Remote Service objects are created by `Central.discover_remote_services()` -//| or `Peripheral.discover_remote_services()`. +//| Create a new Service identitied by the specified UUID. It can be accessed by all +//| connections. This is known as a Service server. Client Service objects are created via +//| `Connection.discover_remote_services`. //| -//| .. classmethod:: add_to_peripheral(peripheral, uuid, *, secondary=False) +//| To mark the Server as secondary, pass `True` as :py:data:`secondary`. //| -//| Create a new Service object, identitied by the specified UUID, and add it -//| to the given Peripheral. -//| -//| To mark the service as secondary, pass `True` as :py:data:`secondary`. -//| -//| :param Peripheral peripheral: The peripheral that will provide this service -//| :param UUID uuid: The uuid of the service -//| :param bool secondary: If the service is a secondary one +//| :param UUID uuid: The uuid of the server +//| :param bool secondary: If the server is a secondary one // -//| :return: the new Service +//| :return: the new Service //| -STATIC mp_obj_t bleio_service_add_to_peripheral(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - // class is arg[0], which we can ignore. - - enum { ARG_peripheral, ARG_uuid, ARG_secondary }; +STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_uuid, ARG_secondary }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_peripheral, MP_ARG_REQUIRED | MP_ARG_OBJ,}, { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_secondary, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - const mp_obj_t peripheral_obj = args[ARG_peripheral].u_obj; - if (!MP_OBJ_IS_TYPE(peripheral_obj, &bleio_peripheral_type)) { - mp_raise_ValueError(translate("Expected a Peripheral")); - } + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); const mp_obj_t uuid_obj = args[ARG_uuid].u_obj; if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { @@ -88,19 +72,15 @@ STATIC mp_obj_t bleio_service_add_to_peripheral(size_t n_args, const mp_obj_t *p bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t); service->base.type = &bleio_service_type; - common_hal_bleio_service_construct( - service, MP_OBJ_TO_PTR(peripheral_obj), MP_OBJ_TO_PTR(uuid_obj), is_secondary); - - common_hal_bleio_peripheral_add_service(peripheral_obj, service); + common_hal_bleio_service_construct(service, MP_OBJ_TO_PTR(uuid_obj), is_secondary); return MP_OBJ_FROM_PTR(service); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_service_add_to_peripheral_fun_obj, 3, bleio_service_add_to_peripheral); -STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_service_add_to_peripheral_obj, MP_ROM_PTR(&bleio_service_add_to_peripheral_fun_obj)); //| .. attribute:: characteristics //| -//| A tuple of :py:class:`Characteristic` designating the characteristics that are offered by this service. (read-only) +//| A tuple of :py:class:`Characteristic` designating the characteristics that are offered by +//| this service. (read-only) //| STATIC mp_obj_t bleio_service_get_characteristics(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -156,7 +136,8 @@ const mp_obj_property_t bleio_service_secondary_obj = { //| .. attribute:: uuid //| //| The UUID of this service. (read-only) -//| Will be ``None`` if the 128-bit UUID for this service is not known. +//| +//| Will be ``None`` if the 128-bit UUID for this service is not known. //| STATIC mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -175,10 +156,10 @@ const mp_obj_property_t bleio_service_uuid_obj = { STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_add_to_peripheral), MP_ROM_PTR(&bleio_service_add_to_peripheral_obj) }, { MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) }, { MP_ROM_QSTR(MP_QSTR_secondary), MP_ROM_PTR(&bleio_service_secondary_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) }, + { MP_ROM_QSTR(MP_QSTR_remote), MP_ROM_PTR(&bleio_service_remote_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_service_locals_dict, bleio_service_locals_dict_table); @@ -196,6 +177,25 @@ STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_pr const mp_obj_type_t bleio_service_type = { { &mp_type_type }, .name = MP_QSTR_Service, + .make_new = bleio_service_make_new, .print = bleio_service_print, .locals_dict = (mp_obj_dict_t*)&bleio_service_locals_dict }; + +// Helper for classes that store lists of services. +mp_obj_tuple_t* service_linked_list_to_tuple(bleio_service_obj_t * services) { + // Return list as a tuple so user won't be able to change it. + bleio_service_obj_t *head = services; + size_t len = 0; + while (head != NULL) { + len++; + head = head->next; + } + mp_obj_tuple_t * t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL)); + head = services; + for (int32_t i = len - 1; i >= 0; i--) { + t->items[i] = MP_OBJ_FROM_PTR(head); + head = head->next; + } + return t; +} diff --git a/shared-bindings/_bleio/Service.h b/shared-bindings/_bleio/Service.h index e061bcffcb..273c6bd989 100644 --- a/shared-bindings/_bleio/Service.h +++ b/shared-bindings/_bleio/Service.h @@ -28,16 +28,24 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H -#include "common-hal/_bleio/Peripheral.h" +#include "common-hal/_bleio/Characteristic.h" +#include "common-hal/_bleio/Connection.h" #include "common-hal/_bleio/Service.h" +#include "py/objtuple.h" + const mp_obj_type_t bleio_service_type; -extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_peripheral_obj_t *peripheral, bleio_uuid_obj_t *uuid, bool is_secondary); +// Private version that doesn't allocate on the heap +extern uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t * characteristic_list); +extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary); +extern void common_hal_bleio_service_from_remote_service(bleio_service_obj_t *self, bleio_connection_obj_t* connection, bleio_uuid_obj_t *uuid, bool is_secondary); extern bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self); extern mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self); extern bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self); extern bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self); -extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic); +extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *initial_value_bufinfo); + +mp_obj_tuple_t* service_linked_list_to_tuple(bleio_service_obj_t * services); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H diff --git a/shared-bindings/_bleio/UUID.c b/shared-bindings/_bleio/UUID.c index 3c0889aad9..dd34159022 100644 --- a/shared-bindings/_bleio/UUID.c +++ b/shared-bindings/_bleio/UUID.c @@ -156,9 +156,10 @@ STATIC mp_obj_t bleio_uuid_get_uuid128(mp_obj_t self_in) { bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in); uint8_t uuid128[16]; - if (!common_hal_bleio_uuid_get_uuid128(self, uuid128)) { + if (common_hal_bleio_uuid_get_size(self) != 128) { mp_raise_AttributeError(translate("not a 128-bit UUID")); } + common_hal_bleio_uuid_get_uuid128(self, uuid128); return mp_obj_new_bytes(uuid128, 16); } @@ -192,10 +193,42 @@ const mp_obj_property_t bleio_uuid_size_obj = { (mp_obj_t)&mp_const_none_obj}, }; + +//| .. method:: pack_into(buffer, offset=0) +//| +//| Packs the UUID into the given buffer at the given offset. +//| +STATIC mp_obj_t bleio_uuid_pack_into(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_buffer, ARG_offset }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_offset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE); + + size_t offset = args[ARG_offset].u_int; + if (offset + common_hal_bleio_uuid_get_size(self) / 8 > bufinfo.len) { + mp_raise_ValueError(translate("Buffer + offset too small %d %d %d")); + } + + common_hal_bleio_uuid_pack_into(self, bufinfo.buf + offset); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_uuid_pack_into_obj, 2, bleio_uuid_pack_into); + STATIC const mp_rom_map_elem_t bleio_uuid_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_uuid16), MP_ROM_PTR(&bleio_uuid_uuid16_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid128), MP_ROM_PTR(&bleio_uuid_uuid128_obj) }, { MP_ROM_QSTR(MP_QSTR_size), MP_ROM_PTR(&bleio_uuid_size_obj) }, + { MP_ROM_QSTR(MP_QSTR_pack_into), MP_ROM_PTR(&bleio_uuid_pack_into_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_uuid_locals_dict, bleio_uuid_locals_dict_table); @@ -231,13 +264,19 @@ STATIC mp_obj_t bleio_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| STATIC mp_obj_t bleio_uuid_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { switch (op) { - // Two UUID's are equal if their uuid16 values and uuid128 references match. + // Two UUID's are equal if their uuid16 values match or their uuid128 values match. case MP_BINARY_OP_EQUAL: if (MP_OBJ_IS_TYPE(rhs_in, &bleio_uuid_type)) { - return mp_obj_new_bool( - common_hal_bleio_uuid_get_uuid16(lhs_in) == common_hal_bleio_uuid_get_uuid16(rhs_in) && - common_hal_bleio_uuid_get_uuid128_reference(lhs_in) == - common_hal_bleio_uuid_get_uuid128_reference(rhs_in)); + if (common_hal_bleio_uuid_get_size(lhs_in) == 16 && + common_hal_bleio_uuid_get_size(rhs_in) == 16) { + return mp_obj_new_bool(common_hal_bleio_uuid_get_uuid16(lhs_in) == + common_hal_bleio_uuid_get_uuid16(rhs_in)); + } + uint8_t lhs[16]; + uint8_t rhs[16]; + common_hal_bleio_uuid_get_uuid128(lhs_in, lhs); + common_hal_bleio_uuid_get_uuid128(rhs_in, rhs); + return mp_obj_new_bool(memcmp(lhs, rhs, sizeof(lhs)) == 0); } else { return mp_const_false; } diff --git a/shared-bindings/_bleio/UUID.h b/shared-bindings/_bleio/UUID.h index 46ac54ff39..1490737a71 100644 --- a/shared-bindings/_bleio/UUID.h +++ b/shared-bindings/_bleio/UUID.h @@ -34,10 +34,11 @@ void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t extern const mp_obj_type_t bleio_uuid_type; -extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, uint8_t uuid128[]); +extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[]); extern uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self); extern bool common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]); -extern uint32_t common_hal_bleio_uuid_get_uuid128_reference(bleio_uuid_obj_t *self); extern uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self); +void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c index f207be8cfc..0c6ebb973b 100644 --- a/shared-bindings/_bleio/__init__.c +++ b/shared-bindings/_bleio/__init__.c @@ -29,13 +29,12 @@ #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Address.h" #include "shared-bindings/_bleio/Attribute.h" -#include "shared-bindings/_bleio/Central.h" #include "shared-bindings/_bleio/Characteristic.h" #include "shared-bindings/_bleio/CharacteristicBuffer.h" +#include "shared-bindings/_bleio/Connection.h" #include "shared-bindings/_bleio/Descriptor.h" -#include "shared-bindings/_bleio/Peripheral.h" #include "shared-bindings/_bleio/ScanEntry.h" -#include "shared-bindings/_bleio/Scanner.h" +#include "shared-bindings/_bleio/ScanResults.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" @@ -64,34 +63,32 @@ //| Address //| Adapter //| Attribute -//| Central //| Characteristic //| CharacteristicBuffer +//| Connection //| Descriptor -//| Peripheral //| ScanEntry -//| Scanner +//| ScanResults //| Service //| UUID //| //| .. attribute:: adapter //| -//| BLE Adapter information, such as enabled state as well as MAC -//| address. +//| BLE Adapter used to manage device discovery and connections. //| This object is the sole instance of `_bleio.Adapter`. //| STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__bleio) }, + { MP_ROM_QSTR(MP_QSTR_Adapter), MP_ROM_PTR(&bleio_adapter_type) }, { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) }, { MP_ROM_QSTR(MP_QSTR_Attribute), MP_ROM_PTR(&bleio_attribute_type) }, - { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) }, + { MP_ROM_QSTR(MP_QSTR_Connection), MP_ROM_PTR(&bleio_connection_type) }, { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) }, { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) }, { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) }, - { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&bleio_peripheral_type) }, { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) }, - { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) }, + { MP_ROM_QSTR(MP_QSTR_ScanResults), MP_ROM_PTR(&bleio_scanresults_type) }, { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) }, { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) }, diff --git a/shared-bindings/_bleio/__init__.h b/shared-bindings/_bleio/__init__.h index 67379ae2e1..92c695fa66 100644 --- a/shared-bindings/_bleio/__init__.h +++ b/shared-bindings/_bleio/__init__.h @@ -36,17 +36,19 @@ #include "common-hal/_bleio/__init__.h" #include "common-hal/_bleio/Adapter.h" -extern const super_adapter_obj_t common_hal_bleio_adapter_obj; +extern bleio_adapter_obj_t common_hal_bleio_adapter_obj; -extern void common_hal_bleio_check_connected(uint16_t conn_handle); +void common_hal_bleio_check_connected(uint16_t conn_handle); -extern uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); -extern mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device); -extern void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist); +uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); +mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device); +void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist); -extern mp_obj_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle); -extern void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo); -extern void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response); +size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len); +void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo); +size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len); +void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response); +void common_hal_bleio_gc_collect(void); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H diff --git a/shared-module/_bleio/ScanEntry.c b/shared-module/_bleio/ScanEntry.c index 8dfa17f31f..785209c4ab 100644 --- a/shared-module/_bleio/ScanEntry.c +++ b/shared-module/_bleio/ScanEntry.c @@ -37,9 +37,50 @@ mp_obj_t common_hal_bleio_scanentry_get_address(bleio_scanentry_obj_t *self) { } mp_obj_t common_hal_bleio_scanentry_get_advertisement_bytes(bleio_scanentry_obj_t *self) { - return self->data; + return MP_OBJ_FROM_PTR(self->data); } mp_int_t common_hal_bleio_scanentry_get_rssi(bleio_scanentry_obj_t *self) { return self->rssi; } + +bool common_hal_bleio_scanentry_get_connectable(bleio_scanentry_obj_t *self) { + return self->connectable; +} + +bool common_hal_bleio_scanentry_get_scan_response(bleio_scanentry_obj_t *self) { + return self->scan_response; +} + +bool bleio_scanentry_data_matches(const uint8_t* data, size_t len, const uint8_t* prefixes, size_t prefixes_length, bool any) { + if (prefixes_length == 0) { + return true; + } + size_t i = 0; + while(i < prefixes_length) { + uint8_t prefix_length = prefixes[i]; + i += 1; + size_t j = 0; + while (j < len) { + uint8_t structure_length = data[j]; + j += 1; + if (structure_length == 0) { + break; + } + if (structure_length >= prefix_length && memcmp(data + j, prefixes + i, prefix_length) == 0) { + if (any) { + return true; + } + } else if (!any) { + return false; + } + j += structure_length; + } + i += prefix_length; + } + return !any; +} + +bool common_hal_bleio_scanentry_matches(bleio_scanentry_obj_t *self, const uint8_t* prefixes, size_t prefixes_len, bool all) { + return bleio_scanentry_data_matches(self->data->data, self->data->len, prefixes, prefixes_len, !all); +} diff --git a/shared-module/_bleio/ScanEntry.h b/shared-module/_bleio/ScanEntry.h index 1e798d78fd..94361a397d 100644 --- a/shared-module/_bleio/ScanEntry.h +++ b/shared-module/_bleio/ScanEntry.h @@ -29,14 +29,19 @@ #define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H #include "py/obj.h" +#include "py/objstr.h" #include "shared-bindings/_bleio/Address.h" typedef struct { mp_obj_base_t base; bool connectable; + bool scan_response; int8_t rssi; bleio_address_obj_t *address; - mp_obj_t data; + mp_obj_str_t *data; + uint64_t time_received; } bleio_scanentry_obj_t; +bool bleio_scanentry_data_matches(const uint8_t* data, size_t len, const uint8_t* prefixes, size_t prefix_length, bool any); + #endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H diff --git a/shared-module/_bleio/ScanResults.c b/shared-module/_bleio/ScanResults.c new file mode 100644 index 0000000000..9f23a836ce --- /dev/null +++ b/shared-module/_bleio/ScanResults.c @@ -0,0 +1,138 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2017 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/_bleio/ScanEntry.h" +#include "shared-bindings/_bleio/ScanResults.h" + +bleio_scanresults_obj_t* shared_module_bleio_new_scanresults(size_t buffer_size, uint8_t* prefixes, size_t prefixes_len, mp_int_t minimum_rssi) { + bleio_scanresults_obj_t* self = m_new_obj(bleio_scanresults_obj_t); + self->base.type = &bleio_scanresults_type; + ringbuf_alloc(&self->buf, buffer_size, false); + self->prefixes = prefixes; + self->prefix_length = prefixes_len; + self->minimum_rssi = minimum_rssi; + return self; +} + +mp_obj_t common_hal_bleio_scanresults_next(bleio_scanresults_obj_t *self) { + while (ringbuf_count(&self->buf) == 0 && !self->done && !mp_exception_pending()) { + RUN_BACKGROUND_TASKS; + } + if (ringbuf_count(&self->buf) == 0 || mp_exception_pending()) { + return mp_const_none; + } + + // Create a ScanEntry out of the data on the buffer. + uint8_t type = ringbuf_get(&self->buf); + bool connectable = (type & (1 << 0)) != 0; + bool scan_response = (type & (1 << 1)) != 0; + uint64_t ticks_ms; + ringbuf_get_n(&self->buf, (uint8_t*) &ticks_ms, sizeof(ticks_ms)); + uint8_t rssi = ringbuf_get(&self->buf); + uint8_t peer_addr[NUM_BLEIO_ADDRESS_BYTES]; + ringbuf_get_n(&self->buf, peer_addr, sizeof(peer_addr)); + uint8_t addr_type = ringbuf_get(&self->buf); + uint16_t len; + ringbuf_get_n(&self->buf, (uint8_t*) &len, sizeof(len)); + + mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_bytes_of_zeros(len)); + ringbuf_get_n(&self->buf, (uint8_t*) o->data, len); + + bleio_scanentry_obj_t *entry = m_new_obj(bleio_scanentry_obj_t); + entry->base.type = &bleio_scanentry_type; + entry->rssi = rssi; + + bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t); + address->base.type = &bleio_address_type; + common_hal_bleio_address_construct(MP_OBJ_TO_PTR(address), peer_addr, addr_type); + entry->address = address; + + entry->data = o; + entry->time_received = ticks_ms; + entry->connectable = connectable; + entry->scan_response = scan_response; + + return MP_OBJ_FROM_PTR(entry); +} + + +void shared_module_bleio_scanresults_append(bleio_scanresults_obj_t* self, + uint64_t ticks_ms, + bool connectable, + bool scan_response, + int8_t rssi, + uint8_t *peer_addr, + uint8_t addr_type, + uint8_t *data, + uint16_t len) { + int32_t packet_size = sizeof(uint8_t) + sizeof(ticks_ms) + sizeof(rssi) + NUM_BLEIO_ADDRESS_BYTES + + sizeof(addr_type) + sizeof(len) + len; + int32_t empty_space = self->buf.size - ringbuf_count(&self->buf); + if (packet_size >= empty_space) { + // We can't fit the packet so skip it. + return; + } + // Filter the packet. + if (rssi < self->minimum_rssi) { + return; + } + + // If any prefixes are provided, then only include packets that include at least one of them. + if (!bleio_scanentry_data_matches(data, len, self->prefixes, self->prefix_length, true)) { + return; + } + uint8_t type = 0; + if (connectable) { + type |= 1 << 0; + } + if (scan_response) { + type |= 1 << 1; + } + + // Add the packet to the buffer. + ringbuf_put(&self->buf, type); + ringbuf_put_n(&self->buf, (uint8_t*) &ticks_ms, sizeof(ticks_ms)); + ringbuf_put(&self->buf, rssi); + ringbuf_put_n(&self->buf, peer_addr, NUM_BLEIO_ADDRESS_BYTES); + ringbuf_put(&self->buf, addr_type); + ringbuf_put_n(&self->buf, (uint8_t*) &len, sizeof(len)); + ringbuf_put_n(&self->buf, data, len); +} + +bool shared_module_bleio_scanresults_get_done(bleio_scanresults_obj_t* self) { + return self->done; +} + +void shared_module_bleio_scanresults_set_done(bleio_scanresults_obj_t* self, bool done) { + self->done = done; + self->common_hal_data = NULL; +} diff --git a/shared-module/_bleio/ScanResults.h b/shared-module/_bleio/ScanResults.h new file mode 100644 index 0000000000..8912357a97 --- /dev/null +++ b/shared-module/_bleio/ScanResults.h @@ -0,0 +1,64 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANRESULTS_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANRESULTS_H + +#include + +#include "py/obj.h" +#include "py/ringbuf.h" + +typedef struct { + mp_obj_base_t base; + // Pointers that needs to live until the scan is done. + void* common_hal_data; + ringbuf_t buf; + // Prefixes is a length encoded array of prefixes. + uint8_t* prefixes; + size_t prefix_length; + mp_int_t minimum_rssi; + bool active; + bool done; +} bleio_scanresults_obj_t; + +bleio_scanresults_obj_t* shared_module_bleio_new_scanresults(size_t buffer_size, uint8_t* prefixes, size_t prefixes_len, mp_int_t minimum_rssi); + +bool shared_module_bleio_scanresults_get_done(bleio_scanresults_obj_t* self); +void shared_module_bleio_scanresults_set_done(bleio_scanresults_obj_t* self, bool done); + +void shared_module_bleio_scanresults_append(bleio_scanresults_obj_t* self, + uint64_t ticks_ms, + bool connectable, + bool scan_result, + int8_t rssi, + uint8_t *peer_addr, + uint8_t addr_type, + uint8_t* data, + uint16_t len); + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANRESULTS_H diff --git a/supervisor/shared/autoreload.c b/supervisor/shared/autoreload.c index 14b21902cd..a6212c1a9b 100644 --- a/supervisor/shared/autoreload.c +++ b/supervisor/shared/autoreload.c @@ -76,3 +76,11 @@ void autoreload_stop() { autoreload_delay_ms = 0; reload_requested = false; } + +void autoreload_now() { + if (!autoreload_enabled || autoreload_suspended || reload_requested) { + return; + } + mp_raise_reload_exception(); + reload_requested = true; +} diff --git a/supervisor/shared/autoreload.h b/supervisor/shared/autoreload.h index bcb1001513..fbd482c19a 100644 --- a/supervisor/shared/autoreload.h +++ b/supervisor/shared/autoreload.h @@ -43,4 +43,6 @@ bool autoreload_is_enabled(void); void autoreload_suspend(void); void autoreload_resume(void); +void autoreload_now(void); + #endif // MICROPY_INCLUDED_SUPERVISOR_AUTORELOAD_H diff --git a/supervisor/shared/bluetooth.c b/supervisor/shared/bluetooth.c new file mode 100644 index 0000000000..64f3b55eb6 --- /dev/null +++ b/supervisor/shared/bluetooth.c @@ -0,0 +1,341 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" + +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/UUID.h" + +#include "common-hal/_bleio/__init__.h" + +#include "supervisor/shared/autoreload.h" + +#include "py/mpstate.h" + +bleio_service_obj_t supervisor_ble_service; +bleio_uuid_obj_t supervisor_ble_service_uuid; +bleio_characteristic_obj_t supervisor_ble_version_characteristic; +bleio_uuid_obj_t supervisor_ble_version_uuid; +bleio_characteristic_obj_t supervisor_ble_filename_characteristic; +bleio_uuid_obj_t supervisor_ble_filename_uuid; +bleio_characteristic_obj_t supervisor_ble_length_characteristic; +bleio_uuid_obj_t supervisor_ble_length_uuid; +bleio_characteristic_obj_t supervisor_ble_contents_characteristic; +bleio_uuid_obj_t supervisor_ble_contents_uuid; +const uint8_t circuitpython_base_uuid[16] = {0x6e, 0x68, 0x74, 0x79, 0x50, 0x74, 0x69, 0x75, 0x63, 0x72, 0x69, 0x43, 0x00, 0x00, 0xaf, 0xad }; +uint8_t circuitpython_advertising_data[] = { 0x02, 0x01, 0x06, 0x02, 0x0a, 0x00, 0x11, 0x07, 0x6e, 0x68, 0x74, 0x79, 0x50, 0x74, 0x69, 0x75, 0x63, 0x72, 0x69, 0x43, 0x00, 0x01, 0xaf, 0xad, 0x06, 0x08, 0x43, 0x49, 0x52, 0x43, 0x55 }; +uint8_t circuitpython_scan_response_data[15] = {0x0e, 0x09, 0x43, 0x49, 0x52, 0x43, 0x55, 0x49, 0x54, 0x50, 0x59, 0x00, 0x00, 0x00, 0x00}; +mp_obj_list_t service_list; +mp_obj_t service_list_items[1]; +mp_obj_list_t characteristic_list; +mp_obj_t characteristic_list_items[4]; + +void supervisor_bluetooth_start_advertising(void) { + bool is_connected = common_hal_bleio_adapter_get_connected(&common_hal_bleio_adapter_obj); + if (is_connected) { + return; + } + // TODO: switch to Adafruit short UUID for the advertisement and add manufacturing data to distinguish ourselves from arduino. + _common_hal_bleio_adapter_start_advertising(&common_hal_bleio_adapter_obj, + true, + 1.0, + circuitpython_advertising_data, + sizeof(circuitpython_advertising_data), + circuitpython_scan_response_data, + sizeof(circuitpython_scan_response_data)); +} + +void supervisor_start_bluetooth(void) { + common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true); + + supervisor_ble_service_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_service_uuid, 0x0100, circuitpython_base_uuid); + + // We know we'll only be 1 characteristic so we can statically allocate it. + characteristic_list.base.type = &mp_type_list; + characteristic_list.alloc = sizeof(characteristic_list_items) / sizeof(characteristic_list_items[0]); + characteristic_list.len = 0; + characteristic_list.items = characteristic_list_items; + mp_seq_clear(characteristic_list.items, 0, characteristic_list.alloc, sizeof(*characteristic_list.items)); + + const uint32_t err_code = _common_hal_bleio_service_construct(&supervisor_ble_service, &supervisor_ble_service_uuid, false /* is secondary */, &characteristic_list); + + // File length + supervisor_ble_version_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_version_uuid, 0x0203, circuitpython_base_uuid); + common_hal_bleio_characteristic_construct(&supervisor_ble_version_characteristic, + &supervisor_ble_service, + 0, // handle (for remote only) + &supervisor_ble_version_uuid, + CHAR_PROP_READ, + SECURITY_MODE_OPEN, + SECURITY_MODE_NO_ACCESS, + 4, // max length + true, // fixed length + NULL); // no initial value + + uint32_t version = 1; + mp_buffer_info_t bufinfo; + bufinfo.buf = &version; + bufinfo.len = sizeof(version); + common_hal_bleio_characteristic_set_value(&supervisor_ble_version_characteristic, &bufinfo); + + // Active filename. + supervisor_ble_filename_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_filename_uuid, 0x0200, circuitpython_base_uuid); + common_hal_bleio_characteristic_construct(&supervisor_ble_filename_characteristic, + &supervisor_ble_service, + 0, // handle (for remote only) + &supervisor_ble_filename_uuid, + CHAR_PROP_READ | CHAR_PROP_WRITE, + SECURITY_MODE_OPEN, + SECURITY_MODE_OPEN, + 500, // max length + false, // fixed length + NULL); // no initial value + + char code_py[] = "/code.py"; + bufinfo.buf = code_py; + bufinfo.len = sizeof(code_py); + common_hal_bleio_characteristic_set_value(&supervisor_ble_filename_characteristic, &bufinfo); + + // File length + supervisor_ble_length_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_length_uuid, 0x0202, circuitpython_base_uuid); + common_hal_bleio_characteristic_construct(&supervisor_ble_length_characteristic, + &supervisor_ble_service, + 0, // handle (for remote only) + &supervisor_ble_length_uuid, + CHAR_PROP_NOTIFY | CHAR_PROP_READ, + SECURITY_MODE_OPEN, + SECURITY_MODE_NO_ACCESS, + 4, // max length + true, // fixed length + NULL); // no initial value + + // File actions + supervisor_ble_contents_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_contents_uuid, 0x0201, circuitpython_base_uuid); + common_hal_bleio_characteristic_construct(&supervisor_ble_contents_characteristic, + &supervisor_ble_service, + 0, // handle (for remote only) + &supervisor_ble_contents_uuid, + CHAR_PROP_NOTIFY | CHAR_PROP_WRITE_NO_RESPONSE | CHAR_PROP_WRITE, + SECURITY_MODE_OPEN, + SECURITY_MODE_OPEN, + 500, // max length + false, // fixed length + NULL); // no initial value + + supervisor_bluetooth_start_advertising(); + vm_used_ble = false; +} + +FIL active_file; +volatile bool new_filename; +volatile bool run_ble_background; +bool was_connected; + +void update_file_length(void) { + int32_t file_length = -1; + mp_buffer_info_t bufinfo; + bufinfo.buf = &file_length; + bufinfo.len = sizeof(file_length); + if (active_file.obj.fs != 0) { + file_length = (int32_t) f_size(&active_file); + } + common_hal_bleio_characteristic_set_value(&supervisor_ble_length_characteristic, &bufinfo); +} + +void open_current_file(void) { + if (active_file.obj.fs != 0) { + return; + } + uint16_t max_len = supervisor_ble_filename_characteristic.max_length; + uint8_t path[max_len]; + size_t length = common_hal_bleio_characteristic_get_value(&supervisor_ble_filename_characteristic, path, max_len - 1); + path[length] = '\0'; + + FATFS *fs = &((fs_user_mount_t *) MP_STATE_VM(vfs_mount_table)->obj)->fatfs; + FRESULT result = f_open(fs, &active_file, (char*) path, FA_READ | FA_WRITE); + + update_file_length(); +} + +void close_current_file(void) { + f_close(&active_file); +} + +uint32_t current_command[1024 / sizeof(uint32_t)]; +volatile size_t current_offset; + +void supervisor_bluetooth_background(void) { + if (!run_ble_background) { + return; + } + bool is_connected = common_hal_bleio_adapter_get_connected(&common_hal_bleio_adapter_obj); + if (!was_connected && is_connected) { + open_current_file(); + } else if (was_connected && !is_connected) { + close_current_file(); + new_filename = false; + } + was_connected = is_connected; + run_ble_background = false; + if (!is_connected) { + supervisor_bluetooth_start_advertising(); + return; + } + if (new_filename) { + close_current_file(); + open_current_file(); + + new_filename = false; + // get length and set the characteristic for it + } + uint16_t current_length = ((uint16_t*) current_command)[0]; + if (current_length > 0 && current_length == current_offset) { + uint16_t command = ((uint16_t *) current_command)[1]; + + if (command == 1) { + uint16_t max_len = 20; //supervisor_ble_contents_characteristic.max_length; + uint8_t buf[max_len]; + mp_buffer_info_t bufinfo; + bufinfo.buf = buf; + f_lseek(&active_file, 0); + while (f_read(&active_file, buf, max_len, &bufinfo.len) == FR_OK) { + if (bufinfo.len == 0) { + break; + } + common_hal_bleio_characteristic_set_value(&supervisor_ble_contents_characteristic, &bufinfo); + } + } else if (command == 2) { // patch + uint32_t offset = current_command[1]; + uint32_t remove_length = current_command[2]; + uint32_t insert_length = current_command[3]; + uint32_t file_length = (int32_t) f_size(&active_file); + //uint32_t data_shift_length = fileLength - offset - remove_length; + int32_t data_shift = insert_length - remove_length; + uint32_t new_length = file_length + data_shift; + FRESULT result; + + // TODO: Make these loops smarter to read and write on sector boundaries. + if (data_shift < 0) { + for (uint32_t shift_offset = offset + insert_length; shift_offset < new_length; shift_offset++) { + uint8_t data; + UINT actual; + f_lseek(&active_file, shift_offset - data_shift); + result = f_read(&active_file, &data, 1, &actual); + f_lseek(&active_file, shift_offset); + result = f_write(&active_file, &data, 1, &actual); + } + f_truncate(&active_file); + } else if (data_shift > 0) { + result = f_lseek(&active_file, file_length); + // Fill end with 0xff so we don't need to erase. + uint8_t data = 0xff; + for (size_t i = 0; i < (size_t) data_shift; i++) { + UINT actual; + result = f_write(&active_file, &data, 1, &actual); + } + for (uint32_t shift_offset = new_length - 1; shift_offset >= offset + insert_length ; shift_offset--) { + UINT actual; + f_lseek(&active_file, shift_offset - data_shift); + result = f_read(&active_file, &data, 1, &actual); + f_lseek(&active_file, shift_offset); + result = f_write(&active_file, &data, 1, &actual); + } + } + + f_lseek(&active_file, offset); + uint8_t* data = (uint8_t *) (current_command + 4); + UINT written; + result = f_write(&active_file, data, insert_length, &written); + f_sync(&active_file); + // Notify the new file length. + update_file_length(); + + // Trigger an autoreload + autoreload_now(); + } + current_offset = 0; + } +} + +// This happens in an interrupt so we need to be quick. +bool supervisor_bluetooth_hook(ble_evt_t *ble_evt) { + // Catch writes to filename or contents. Length is read-only. + + bool done = false; + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + // We run our background task even if it wasn't us connected to because we may want to + // advertise if the user code stopped advertising. + run_ble_background = true; + break; + case BLE_GAP_EVT_DISCONNECTED: + run_ble_background = true; + break; + case BLE_GATTS_EVT_WRITE: { + // A client wrote to a characteristic. + + ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write; + // Event handle must match the handle for my characteristic. + if (evt_write->handle == supervisor_ble_contents_characteristic.handle) { + // Handle events + //write_to_ringbuf(self, evt_write->data, evt_write->len); + // First packet includes a uint16_t le for length at the start. + uint16_t current_length = ((uint16_t*) current_command)[0]; + memcpy(((uint8_t*) current_command) + current_offset, evt_write->data, evt_write->len); + current_offset += evt_write->len; + current_length = ((uint16_t*) current_command)[0]; + if (current_offset == current_length) { + run_ble_background = true; + done = true; + } + } else if (evt_write->handle == supervisor_ble_filename_characteristic.handle) { + new_filename = true; + run_ble_background = true; + done = true; + } else { + return done; + } + break; + } + + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id); + break; + } + return done; +} diff --git a/ports/nrf/common-hal/_bleio/Central.h b/supervisor/shared/bluetooth.h similarity index 66% rename from ports/nrf/common-hal/_bleio/Central.h rename to supervisor/shared/bluetooth.h index 01f7faca74..7ebcb953f0 100644 --- a/ports/nrf/common-hal/_bleio/Central.h +++ b/supervisor/shared/bluetooth.h @@ -3,8 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,20 +24,11 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H -#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H +#ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H +#define MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H -#include +void supervisor_start_bluetooth(void); +bool supervisor_bluetooth_hook(ble_evt_t *ble_evt); +void supervisor_bluetooth_background(void); -#include "py/objlist.h" -#include "shared-module/_bleio/Address.h" - -typedef struct { - mp_obj_base_t base; - volatile bool waiting_to_connect; - volatile uint16_t conn_handle; - // Services discovered after connecting to a remote peripheral. - mp_obj_list_t *remote_service_list; -} bleio_central_obj_t; - -#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H +#endif \ No newline at end of file diff --git a/supervisor/shared/safe_mode.h b/supervisor/shared/safe_mode.h index ee0723cff1..8c5dcd9c5d 100644 --- a/supervisor/shared/safe_mode.h +++ b/supervisor/shared/safe_mode.h @@ -37,7 +37,8 @@ typedef enum { MICROPY_NLR_JUMP_FAIL, MICROPY_FATAL_ERROR, GC_ALLOC_OUTSIDE_VM, - PROGRAMMATIC_SAFE_MODE + PROGRAMMATIC_SAFE_MODE, + NORDIC_SOFT_DEVICE_ASSERT } safe_mode_t; safe_mode_t wait_for_safe_mode_reset(void); diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index 48697a94ae..ad0f716fbf 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -28,6 +28,11 @@ ifneq ($(SPI_FLASH_FILESYSTEM),) CFLAGS += -DSPI_FLASH_FILESYSTEM=$(SPI_FLASH_FILESYSTEM) -DEXPRESS_BOARD endif + +ifeq ($(CIRCUITPY_BLEIO),1) + SRC_SUPERVISOR += supervisor/shared/bluetooth.c +endif + # Choose which flash filesystem impl to use. # (Right now INTERNAL_FLASH_FILESYSTEM and SPI_FLASH_FILESYSTEM are mutually exclusive. # But that might not be true in the future.) From aeee15eae8dc83f2947ac57ca868e439a15bf84b Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 21 Oct 2019 19:50:17 -0700 Subject: [PATCH 02/38] Update translations --- locale/ID.po | 153 ++++++++++++++++++++-------------- locale/circuitpython.pot | 109 ++++++++++++------------ locale/de_DE.po | 174 +++++++++++++++++++++++---------------- locale/en_US.po | 109 ++++++++++++------------ locale/en_x_pirate.po | 109 ++++++++++++------------ locale/es.po | 149 +++++++++++++++++++-------------- locale/fil.po | 149 +++++++++++++++++++-------------- locale/fr.po | 153 ++++++++++++++++++++-------------- locale/it_IT.po | 149 +++++++++++++++++++-------------- locale/pl.po | 149 +++++++++++++++++++-------------- locale/pt_BR.po | 149 +++++++++++++++++++-------------- locale/zh_Latn_pinyin.po | 168 +++++++++++++++++++++++-------------- 12 files changed, 983 insertions(+), 737 deletions(-) diff --git a/locale/ID.po b/locale/ID.po index 63e3466b6e..9c70789af6 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -261,6 +261,10 @@ msgstr "Semua timer untuk pin ini sedang digunakan" msgid "All timers in use" msgstr "Semua timer sedang digunakan" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "fungsionalitas AnalogOut tidak didukung" @@ -329,6 +333,11 @@ msgstr "" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -465,6 +474,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -507,7 +522,7 @@ msgstr "" msgid "Data chunk must follow fmt chunk" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy msgid "Data too large for advertisement packet" msgstr "Tidak bisa menyesuaikan data ke dalam paket advertisment" @@ -554,10 +569,6 @@ msgstr "" msgid "Expected a Characteristic" msgstr "" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -567,7 +578,7 @@ msgstr "" msgid "Expected a UUID" msgstr "" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -576,6 +587,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -586,20 +602,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Gagal untuk mendapatkan mutex, status: 0x%08lX" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Gagal untuk menambahkan karakteristik, status: 0x%08lX" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Gagal untuk menambahkan layanan, status: 0x%08lX" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Gagal untuk mengalokasikan buffer RX" @@ -611,25 +621,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Gagal untuk megalokasikan buffer RX dari %d byte" #: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy -msgid "Failed to change softdevice state" -msgstr "Gagal untuk merubah status softdevice, error: 0x%08lX" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, fuzzy, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Gagal untuk melanjutkan scanning, status: 0x%08lX" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "Gagal untuk menemukan layanan, status: 0x%08lX" @@ -649,7 +656,7 @@ msgstr "Gagal untuk mendapatkan status softdevice, error: 0x%08lX" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -658,8 +665,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Gagal untuk membaca nilai atribut, status: 0x%08lX" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -679,35 +685,27 @@ msgstr "Gagal untuk menambahkan Vendor Spesific UUID, status: 0x%08lX" msgid "Failed to release mutex, err 0x%04x" msgstr "Gagal untuk melepaskan mutex, status: 0x%08lX" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Gagal untuk memulai advertisement, status: 0x%08lX" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Gagal untuk melakukan scanning, status: 0x%08lX" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Gagal untuk memberhentikan advertisement, status: 0x%08lX" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1004,9 +1002,8 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Tidak dapat menyambungkan ke AP" @@ -1081,6 +1078,10 @@ msgstr "Tambahkan module apapun pada filesystem\n" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1151,6 +1152,10 @@ msgstr "" msgid "Sample rate too high. It must be less than %d" msgstr "Nilai sampel terlalu tinggi. Nilai harus kurang dari %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1165,11 +1170,6 @@ msgstr "" msgid "Slices not supported" msgstr "" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "Dukungan soft device, id: 0x%08lX, pc: 0x%08l" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Memisahkan dengan menggunakan sub-captures" @@ -1984,7 +1984,7 @@ msgstr "" msgid "integer required" msgstr "" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2161,11 +2161,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "" -#: shared-bindings/_bleio/Peripheral.c -#, fuzzy -msgid "name must be a string" -msgstr "keyword harus berupa string" - #: py/runtime.c msgid "name not defined" msgstr "" @@ -2216,7 +2211,7 @@ msgstr "" msgid "no such attribute" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2700,7 +2695,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2770,10 +2765,22 @@ msgstr "" #~ msgid "Failed to acquire mutex" #~ msgstr "Gagal untuk mendapatkan mutex, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Gagal untuk menambahkan karakteristik, status: 0x%08lX" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "Gagal untuk menambahkan layanan, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Gagal untuk menambahkan layanan, status: 0x%08lX" + +#, fuzzy +#~ msgid "Failed to change softdevice state" +#~ msgstr "Gagal untuk merubah status softdevice, error: 0x%08lX" + #, fuzzy #~ msgid "Failed to connect:" #~ msgstr "Gagal untuk menyambungkan, status: 0x%08lX" @@ -2782,6 +2789,10 @@ msgstr "" #~ msgid "Failed to continue scanning" #~ msgstr "Gagal untuk melanjutkan scanning, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Gagal untuk melanjutkan scanning, status: 0x%08lX" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "Gagal untuk membuat mutex, status: 0x%08lX" @@ -2802,6 +2813,10 @@ msgstr "" #~ msgid "Failed to start advertising" #~ msgstr "Gagal untuk memulai advertisement, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Gagal untuk memulai advertisement, status: 0x%08lX" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "Gagal untuk melakukan scanning, status: 0x%08lX" @@ -2810,6 +2825,10 @@ msgstr "" #~ msgid "Failed to stop advertising" #~ msgstr "Gagal untuk memberhentikan advertisement, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Gagal untuk memberhentikan advertisement, status: 0x%08lX" + #~ msgid "GPIO16 does not support pull up." #~ msgstr "GPIO16 tidak mendukung pull up" @@ -2859,6 +2878,10 @@ msgstr "" #~ msgid "STA required" #~ msgstr "STA dibutuhkan" +#, fuzzy, c-format +#~ msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +#~ msgstr "Dukungan soft device, id: 0x%08lX, pc: 0x%08l" + #~ msgid "UART(%d) does not exist" #~ msgstr "UART(%d) tidak ada" @@ -2936,6 +2959,10 @@ msgstr "" #~ msgid "memory allocation failed, allocating %u bytes for native code" #~ msgstr "alokasi memori gagal, mengalokasikan %u byte untuk kode native" +#, fuzzy +#~ msgid "name must be a string" +#~ msgstr "keyword harus berupa string" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "tidak valid channel ADC: %d" diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index d709a69cc9..34aa3ff0aa 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -259,6 +259,10 @@ msgstr "" msgid "All timers in use" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "" @@ -325,6 +329,11 @@ msgstr "" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -455,6 +464,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -497,7 +512,7 @@ msgstr "" msgid "Data chunk must follow fmt chunk" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "" @@ -543,10 +558,6 @@ msgstr "" msgid "Expected a Characteristic" msgstr "" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -556,7 +567,7 @@ msgstr "" msgid "Expected a UUID" msgstr "" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -565,6 +576,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -575,8 +591,7 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "" #: ports/nrf/common-hal/_bleio/Service.c -#, c-format -msgid "Failed to add characteristic, err 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -584,11 +599,6 @@ msgstr "" msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "" @@ -600,24 +610,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "" @@ -634,7 +642,7 @@ msgstr "" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -643,8 +651,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -664,34 +671,26 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -989,9 +988,8 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "" @@ -1065,6 +1063,10 @@ msgstr "" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1131,6 +1133,10 @@ msgstr "" msgid "Sample rate too high. It must be less than %d" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1145,11 +1151,6 @@ msgstr "" msgid "Slices not supported" msgstr "" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "" @@ -1950,7 +1951,7 @@ msgstr "" msgid "integer required" msgstr "" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2127,10 +2128,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "" - #: py/runtime.c msgid "name not defined" msgstr "" @@ -2181,7 +2178,7 @@ msgstr "" msgid "no such attribute" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2663,7 +2660,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" diff --git a/locale/de_DE.po b/locale/de_DE.po index b790e86bdf..be8fe0726f 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: Pascal Deneaux\n" "Language-Team: Sebastian Plamauer, Pascal Deneaux\n" @@ -261,6 +261,10 @@ msgstr "Alle timer für diesen Pin werden bereits benutzt" msgid "All timers in use" msgstr "Alle timer werden benutzt" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "AnalogOut-Funktion wird nicht unterstützt" @@ -329,6 +333,11 @@ msgstr "Die Helligkeit muss zwischen 0 und 255 liegen" msgid "Brightness not adjustable" msgstr "Die Helligkeit ist nicht einstellbar" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -459,6 +468,12 @@ msgstr "Der Befehl muss zwischen 0 und 255 liegen" msgid "Command must be an int between 0 and 255" msgstr "Der Befehl muss ein int zwischen 0 und 255 sein" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Beschädigte .mpy Datei" @@ -501,7 +516,7 @@ msgstr "Data 0 pin muss am Byte ausgerichtet sein" msgid "Data chunk must follow fmt chunk" msgstr "Dem fmt Block muss ein Datenblock folgen" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "Zu vielen Daten für das advertisement packet" @@ -547,10 +562,6 @@ msgstr "Erwartet ein(e) %q" msgid "Expected a Characteristic" msgstr "Characteristic wird erwartet" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "Ein Peripheriegerät wird erwartet" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Ein Service wird erwartet" @@ -560,7 +571,7 @@ msgstr "Ein Service wird erwartet" msgid "Expected a UUID" msgstr "Eine UUID wird erwartet" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "Erwartet eine Adresse" @@ -569,6 +580,11 @@ msgstr "Erwartet eine Adresse" msgid "Expected tuple of length %d, got %d" msgstr "Habe ein Tupel der Länge %d erwartet aber %d erhalten" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "Kommando nicht gesendet." @@ -579,20 +595,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Mutex konnte nicht akquiriert werden. Status: 0x%04x" #: ports/nrf/common-hal/_bleio/Service.c -#, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Hinzufügen des Characteristic ist gescheitert. Status: 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "Deskriptor konnte nicht hinzugefügt werden. Status: 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Dienst konnte nicht hinzugefügt werden. Status: 0x%04x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Konnte keinen RX Buffer allozieren" @@ -604,24 +614,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Konnte keine RX Buffer mit %d allozieren" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" -msgstr "Fehler beim Ändern des Softdevice-Status" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "Verbindung nicht erfolgreich: timeout" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Der Scanvorgang kann nicht fortgesetzt werden. Status: 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "Es konnten keine Dienste gefunden werden" @@ -638,7 +646,7 @@ msgstr "Fehler beim Abrufen des Softdevice-Status" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "Koppeln fehlgeschlagen" @@ -647,8 +655,7 @@ msgstr "Koppeln fehlgeschlagen" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Kann CCCD value nicht lesen. Status: 0x%04x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Kann Attributwert nicht lesen, Status: 0x%04x" @@ -668,35 +675,27 @@ msgstr "Kann keine herstellerspezifische UUID hinzufügen. Status: 0x%04x" msgid "Failed to release mutex, err 0x%04x" msgstr "Mutex konnte nicht freigegeben werden. Status: 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" -msgstr "Gerätename konnte nicht gesetzt werden, Status: 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Kann advertisement nicht starten. Status: 0x%04x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "Verbindung konnte nicht hergestellt werden. Status: 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" -msgstr "Starten des Koppelns fehlgeschlagen, Status: 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Der Scanvorgang kann nicht gestartet werden. Status: 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Kann advertisement nicht stoppen. Status: 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1002,9 +1001,8 @@ msgstr "Kein Speicherplatz mehr verfügbar auf dem Gerät" msgid "No such file/directory" msgstr "Keine solche Datei/Verzeichnis" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "Nicht verbunden" @@ -1033,7 +1031,8 @@ msgstr "Nur 8 oder 16 bit mono mit " msgid "" "Only Windows format, uncompressed BMP supported: given header size is %d" msgstr "" -"Nur Windows-Format, unkomprimiertes BMP unterstützt: die gegebene Header-Größe ist %d" +"Nur Windows-Format, unkomprimiertes BMP unterstützt: die gegebene Header-" +"Größe ist %d" #: shared-module/displayio/OnDiskBitmap.c #, c-format @@ -1041,8 +1040,8 @@ msgid "" "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " "%d bpp given" msgstr "" -"Nur monochrome, indizierte 4bpp oder 8bpp, und 16bpp oder größere BMPs unterstützt: " -"%d bpp wurden gegeben" +"Nur monochrome, indizierte 4bpp oder 8bpp, und 16bpp oder größere BMPs " +"unterstützt: %d bpp wurden gegeben" #: shared-bindings/_pixelbuf/PixelBuf.c msgid "Only slices with step=1 (aka None) are supported" @@ -1083,6 +1082,10 @@ msgstr "und alle Module im Dateisystem \n" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1151,6 +1154,10 @@ msgstr "Abtastrate muss positiv sein" msgid "Sample rate too high. It must be less than %d" msgstr "Abtastrate zu hoch. Wert muss unter %d liegen" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1165,11 +1172,6 @@ msgstr "Slice und Wert (value) haben unterschiedliche Längen." msgid "Slices not supported" msgstr "Slices werden nicht unterstützt" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Splitting mit sub-captures" @@ -1202,8 +1204,8 @@ msgid "" "The `microcontroller` module was used to boot into safe mode. Press reset to " "exit safe mode.\n" msgstr "" -"Das `Mikrocontroller` Modul wurde benutzt, um in den Sicherheitsmodus zu starten. " -"Drücke Reset um den Sicherheitsmodus zu verlassen.\n" +"Das `Mikrocontroller` Modul wurde benutzt, um in den Sicherheitsmodus zu " +"starten. Drücke Reset um den Sicherheitsmodus zu verlassen.\n" #: supervisor/shared/safe_mode.c msgid "" @@ -1740,7 +1742,8 @@ msgstr "Farbpuffer muss ein Puffer oder ein int sein" #: shared-bindings/displayio/Palette.c msgid "color buffer must be a bytearray or array of type 'b' or 'B'" -msgstr "Farbpuffer muss ein Byte-Array oder ein Array vom Typ 'b' oder 'B' sein" +msgstr "" +"Farbpuffer muss ein Byte-Array oder ein Array vom Typ 'b' oder 'B' sein" #: shared-bindings/displayio/Palette.c msgid "color must be between 0x000000 and 0xffffff" @@ -1996,7 +1999,7 @@ msgstr "int() arg 2 muss >= 2 und <= 36 sein" msgid "integer required" msgstr "integer erforderlich" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "Das Intervall muss im Bereich %s-%s sein" @@ -2179,10 +2182,6 @@ msgstr "muss Schlüsselwortargument für key function verwenden" msgid "name '%q' is not defined" msgstr "Name '%q' ist nirgends definiert worden (Schreibweise kontrollieren)" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "name muss ein String sein" - #: py/runtime.c msgid "name not defined" msgstr "Dieser Name ist nirgends definiert worden (Schreibweise kontrollieren)" @@ -2233,7 +2232,7 @@ msgstr "kein Reset Pin verfügbar" msgid "no such attribute" msgstr "kein solches Attribut" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2724,7 +2723,7 @@ msgstr "Wert muss in %d Byte(s) passen" msgid "value_count must be > 0" msgstr "value_count muss größer als 0 sein" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2811,18 +2810,36 @@ msgstr "" #~ msgid "Error in ffi_prep_cif" #~ msgstr "Fehler in ffi_prep_cif" +#~ msgid "Expected a Peripheral" +#~ msgstr "Ein Peripheriegerät wird erwartet" + #~ msgid "Failed to acquire mutex" #~ msgstr "Akquirieren des Mutex gescheitert" +#, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Hinzufügen des Characteristic ist gescheitert. Status: 0x%04x" + #~ msgid "Failed to add service" #~ msgstr "Dienst konnte nicht hinzugefügt werden" +#, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Dienst konnte nicht hinzugefügt werden. Status: 0x%04x" + +#~ msgid "Failed to change softdevice state" +#~ msgstr "Fehler beim Ändern des Softdevice-Status" + #~ msgid "Failed to connect:" #~ msgstr "Verbindung fehlgeschlagen:" #~ msgid "Failed to continue scanning" #~ msgstr "Der Scanvorgang kann nicht fortgesetzt werden" +#, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Der Scanvorgang kann nicht fortgesetzt werden. Status: 0x%04x" + #~ msgid "Failed to create mutex" #~ msgstr "Erstellen des Mutex ist fehlgeschlagen" @@ -2835,15 +2852,31 @@ msgstr "" #~ msgid "Failed to release mutex" #~ msgstr "Loslassen des Mutex gescheitert" +#, c-format +#~ msgid "Failed to set device name, err 0x%04x" +#~ msgstr "Gerätename konnte nicht gesetzt werden, Status: 0x%04x" + #~ msgid "Failed to start advertising" #~ msgstr "Kann advertisement nicht starten" +#, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Kann advertisement nicht starten. Status: 0x%04x" + +#, c-format +#~ msgid "Failed to start pairing, error 0x%04x" +#~ msgstr "Starten des Koppelns fehlgeschlagen, Status: 0x%04x" + #~ msgid "Failed to start scanning" #~ msgstr "Der Scanvorgang kann nicht gestartet werden" #~ msgid "Failed to stop advertising" #~ msgstr "Kann advertisement nicht stoppen" +#, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Kann advertisement nicht stoppen. Status: 0x%04x" + #~ msgid "Function requires lock." #~ msgstr "" #~ "Die Funktion erwartet, dass der 'lock'-Befehl zuvor ausgeführt wurde" @@ -2977,6 +3010,9 @@ msgstr "" #~ msgstr "" #~ "Speicherallozierung fehlgeschlagen, alloziere %u Bytes für nativen Code" +#~ msgid "name must be a string" +#~ msgstr "name muss ein String sein" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "Kein gültiger ADC Kanal: %d" diff --git a/locale/en_US.po b/locale/en_US.po index 652053ee99..b30e17cecc 100644 --- a/locale/en_US.po +++ b/locale/en_US.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: \n" "Language-Team: \n" @@ -259,6 +259,10 @@ msgstr "" msgid "All timers in use" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "" @@ -325,6 +329,11 @@ msgstr "" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -455,6 +464,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -497,7 +512,7 @@ msgstr "" msgid "Data chunk must follow fmt chunk" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "" @@ -543,10 +558,6 @@ msgstr "" msgid "Expected a Characteristic" msgstr "" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -556,7 +567,7 @@ msgstr "" msgid "Expected a UUID" msgstr "" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -565,6 +576,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -575,8 +591,7 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "" #: ports/nrf/common-hal/_bleio/Service.c -#, c-format -msgid "Failed to add characteristic, err 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -584,11 +599,6 @@ msgstr "" msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "" @@ -600,24 +610,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "" @@ -634,7 +642,7 @@ msgstr "" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -643,8 +651,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -664,34 +671,26 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -989,9 +988,8 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "" @@ -1065,6 +1063,10 @@ msgstr "" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1131,6 +1133,10 @@ msgstr "" msgid "Sample rate too high. It must be less than %d" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1145,11 +1151,6 @@ msgstr "" msgid "Slices not supported" msgstr "" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "" @@ -1950,7 +1951,7 @@ msgstr "" msgid "integer required" msgstr "" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2127,10 +2128,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "" - #: py/runtime.c msgid "name not defined" msgstr "" @@ -2181,7 +2178,7 @@ msgstr "" msgid "no such attribute" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2663,7 +2660,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" diff --git a/locale/en_x_pirate.po b/locale/en_x_pirate.po index 1d2fcb659c..f9bb0a4002 100644 --- a/locale/en_x_pirate.po +++ b/locale/en_x_pirate.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: \n" "Language-Team: @sommersoft, @MrCertainly\n" @@ -261,6 +261,10 @@ msgstr "" msgid "All timers in use" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "" @@ -329,6 +333,11 @@ msgstr "" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -459,6 +468,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -501,7 +516,7 @@ msgstr "" msgid "Data chunk must follow fmt chunk" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "" @@ -547,10 +562,6 @@ msgstr "" msgid "Expected a Characteristic" msgstr "" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -560,7 +571,7 @@ msgstr "" msgid "Expected a UUID" msgstr "" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -569,6 +580,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -579,8 +595,7 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "" #: ports/nrf/common-hal/_bleio/Service.c -#, c-format -msgid "Failed to add characteristic, err 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -588,11 +603,6 @@ msgstr "" msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "" @@ -604,24 +614,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "" @@ -638,7 +646,7 @@ msgstr "" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -647,8 +655,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -668,34 +675,26 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -993,9 +992,8 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "" @@ -1069,6 +1067,10 @@ msgstr "" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1135,6 +1137,10 @@ msgstr "" msgid "Sample rate too high. It must be less than %d" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1149,11 +1155,6 @@ msgstr "" msgid "Slices not supported" msgstr "" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "" @@ -1954,7 +1955,7 @@ msgstr "" msgid "integer required" msgstr "" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2131,10 +2132,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "" - #: py/runtime.c msgid "name not defined" msgstr "" @@ -2185,7 +2182,7 @@ msgstr "" msgid "no such attribute" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2667,7 +2664,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" diff --git a/locale/es.po b/locale/es.po index ca8593dcdf..8bcfcedbe3 100644 --- a/locale/es.po +++ b/locale/es.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-08-24 22:56-0500\n" "Last-Translator: \n" "Language-Team: \n" @@ -263,6 +263,10 @@ msgstr "Todos los timers para este pin están siendo utilizados" msgid "All timers in use" msgstr "Todos los timers en uso" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "Funcionalidad AnalogOut no soportada" @@ -333,6 +337,11 @@ msgstr "El brillo debe estar entro 0 y 255" msgid "Brightness not adjustable" msgstr "El brillo no se puede ajustar" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -463,6 +472,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "Command debe estar entre 0 y 255." +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -505,7 +520,7 @@ msgstr "El pin Data 0 debe estar alineado a bytes" msgid "Data chunk must follow fmt chunk" msgstr "Trozo de datos debe seguir fmt chunk" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "Data es muy grande para el paquete de advertisement." @@ -551,10 +566,6 @@ msgstr "Se espera un %q" msgid "Expected a Characteristic" msgstr "Se esperaba una Característica." -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -564,7 +575,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Se esperaba un UUID" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -573,6 +584,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "Se esperaba un tuple de %d, se obtuvo %d" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "Fallo enviando comando" @@ -583,20 +599,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "No se puede adquirir el mutex, status: 0x%08lX" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Fallo al añadir caracteristica, err: 0x%08lX" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Fallo al agregar servicio. err: 0x%02x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Ha fallado la asignación del buffer RX" @@ -608,24 +618,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Falló la asignación del buffer RX de %d bytes" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" -msgstr "No se puede cambiar el estado del softdevice" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "No se puede iniciar el escaneo. err: 0x%02x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "No se puede descubrir servicios" @@ -643,7 +651,7 @@ msgstr "No se puede obtener el estado del softdevice" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Error al notificar o indicar el valor del atributo, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -652,8 +660,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "No se puede leer el valor del atributo. err 0x%02x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, fuzzy, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Error al leer valor del atributo, err 0x%04" @@ -673,35 +680,27 @@ msgstr "Fallo al registrar el Vendor-Specific UUID, err 0x%04x" msgid "Failed to release mutex, err 0x%04x" msgstr "No se puede liberar el mutex, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "No se puede inicar el anuncio. err: 0x%04x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "No se puede iniciar el escaneo. err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "No se puede detener el anuncio. err: 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1004,9 +1003,8 @@ msgstr "No queda espacio en el dispositivo" msgid "No such file/directory" msgstr "No existe el archivo/directorio" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "No conectado" @@ -1088,6 +1086,10 @@ msgstr "Incapaz de montar de nuevo el sistema de archivos" msgid "Pop from an empty Ps2 buffer" msgstr "Pop de un buffer Ps2 vacio" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1157,6 +1159,10 @@ msgstr "Sample rate debe ser positivo" msgid "Sample rate too high. It must be less than %d" msgstr "Frecuencia de muestreo demasiado alta. Debe ser menor a %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1171,11 +1177,6 @@ msgstr "Slice y value tienen diferentes longitudes" msgid "Slices not supported" msgstr "Rebanadas no soportadas" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "Soft device assert, id: 0x%08lX, pc: 0x%08lX" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Dividiendo con sub-capturas" @@ -2004,7 +2005,7 @@ msgstr "int() arg 2 debe ser >= 2 y <= 36" msgid "integer required" msgstr "Entero requerido" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2184,10 +2185,6 @@ msgstr "debe utilizar argumento de palabra clave para la función clave" msgid "name '%q' is not defined" msgstr "name '%q' no esta definido" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "name debe de ser un string" - #: py/runtime.c msgid "name not defined" msgstr "name no definido" @@ -2238,7 +2235,7 @@ msgstr "" msgid "no such attribute" msgstr "no hay tal atributo" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2728,7 +2725,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2818,10 +2815,21 @@ msgstr "paso cero" #~ msgid "Failed to acquire mutex" #~ msgstr "No se puede adquirir el mutex, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Fallo al añadir caracteristica, err: 0x%08lX" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "No se puede detener el anuncio. status: 0x%02x" +#, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Fallo al agregar servicio. err: 0x%02x" + +#~ msgid "Failed to change softdevice state" +#~ msgstr "No se puede cambiar el estado del softdevice" + #, fuzzy #~ msgid "Failed to connect:" #~ msgstr "No se puede conectar. status: 0x%02x" @@ -2830,6 +2838,10 @@ msgstr "paso cero" #~ msgid "Failed to continue scanning" #~ msgstr "No se puede iniciar el escaneo. status: 0x%02x" +#, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "No se puede iniciar el escaneo. err: 0x%02x" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "No se puede leer el valor del atributo. status 0x%02x" @@ -2850,6 +2862,10 @@ msgstr "paso cero" #~ msgid "Failed to start advertising" #~ msgstr "No se puede inicar el anuncio. status: 0x%02x" +#, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "No se puede inicar el anuncio. err: 0x%04x" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "No se puede iniciar el escaneo. status: 0x%02x" @@ -2858,6 +2874,10 @@ msgstr "paso cero" #~ msgid "Failed to stop advertising" #~ msgstr "No se puede detener el anuncio. status: 0x%02x" +#, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "No se puede detener el anuncio. err: 0x%04x" + #~ msgid "Function requires lock." #~ msgstr "La función requiere lock" @@ -2932,6 +2952,10 @@ msgstr "paso cero" #~ msgid "STA required" #~ msgstr "STA requerido" +#, c-format +#~ msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +#~ msgstr "Soft device assert, id: 0x%08lX, pc: 0x%08lX" + #~ msgid "Tile indices must be 0 - 255" #~ msgstr "Los índices de Tile deben ser 0 - 255" @@ -3027,6 +3051,9 @@ msgstr "paso cero" #~ msgstr "" #~ "falló la asignación de memoria, asignando %u bytes para código nativo" +#~ msgid "name must be a string" +#~ msgstr "name debe de ser un string" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "no es un canal ADC válido: %d" diff --git a/locale/fil.po b/locale/fil.po index 6f460c94cf..2223ee7793 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-12-20 22:15-0800\n" "Last-Translator: Timothy \n" "Language-Team: fil\n" @@ -263,6 +263,10 @@ msgstr "Lahat ng timers para sa pin na ito ay ginagamit" msgid "All timers in use" msgstr "Lahat ng timer ginagamit" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "Hindi supportado ang AnalogOut" @@ -331,6 +335,11 @@ msgstr "Ang liwanag ay dapat sa gitna ng 0 o 255" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -464,6 +473,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "Sa gitna ng 0 o 255 dapat ang bytes." +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -507,7 +522,7 @@ msgstr "graphic ay dapat 2048 bytes ang haba" msgid "Data chunk must follow fmt chunk" msgstr "Dapat sunurin ng Data chunk ang fmt chunk" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy msgid "Data too large for advertisement packet" msgstr "Hindi makasya ang data sa loob ng advertisement packet" @@ -556,10 +571,6 @@ msgstr "Umasa ng %q" msgid "Expected a Characteristic" msgstr "Hindi mabasa and Characteristic." -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -570,7 +581,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Umasa ng %q" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -579,6 +590,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -589,20 +605,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Nabigo sa pag kuha ng mutex, status: 0x%08lX" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Nabigo sa paglagay ng characteristic, status: 0x%08lX" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Hindi matagumpay ang paglagay ng service, status: 0x%08lX" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Nabigong ilaan ang RX buffer" @@ -614,25 +624,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Nabigong ilaan ang RX buffer ng %d bytes" #: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy -msgid "Failed to change softdevice state" -msgstr "Nabigo sa pagbago ng softdevice state, error: 0x%08lX" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, fuzzy, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Hindi maituloy ang pag scan, status: 0x%0xlX" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "Nabigo sa pagdiscover ng services, status: 0x%08lX" @@ -652,7 +659,7 @@ msgstr "Nabigo sa pagkuha ng softdevice state, error: 0x%08lX" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -661,8 +668,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Hindi mabasa ang value ng attribute, status: 0x%08lX" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -682,35 +688,27 @@ msgstr "Hindi matagumpay ang paglagay ng Vender Specific UUID, status: 0x%08lX" msgid "Failed to release mutex, err 0x%04x" msgstr "Nabigo sa pagrelease ng mutex, status: 0x%08lX" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Hindi masimulaan ang advertisement, status: 0x%08lX" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Hindi masimulaan mag i-scan, status: 0x%0xlX" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Hindi mahinto ang advertisement, status: 0x%08lX" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1013,9 +1011,8 @@ msgstr "" msgid "No such file/directory" msgstr "Walang file/directory" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Hindi maka connect sa AP" @@ -1094,6 +1091,10 @@ msgstr "Kasama ang kung ano pang modules na sa filesystem\n" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1164,6 +1165,10 @@ msgstr "Sample rate ay dapat positibo" msgid "Sample rate too high. It must be less than %d" msgstr "Sample rate ay masyadong mataas. Ito ay dapat hindi hiigit sa %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1178,11 +1183,6 @@ msgstr "Slice at value iba't ibang haba." msgid "Slices not supported" msgstr "Hindi suportado ang Slices" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Binibiyak gamit ang sub-captures" @@ -2016,7 +2016,7 @@ msgstr "int() arg 2 ay dapat >=2 at <= 36" msgid "integer required" msgstr "kailangan ng int" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2197,11 +2197,6 @@ msgstr "dapat gumamit ng keyword argument para sa key function" msgid "name '%q' is not defined" msgstr "name '%q' ay hindi defined" -#: shared-bindings/_bleio/Peripheral.c -#, fuzzy -msgid "name must be a string" -msgstr "ang keywords dapat strings" - #: py/runtime.c msgid "name not defined" msgstr "name hindi na define" @@ -2252,7 +2247,7 @@ msgstr "" msgid "no such attribute" msgstr "walang ganoon na attribute" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2741,7 +2736,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2825,10 +2820,22 @@ msgstr "zero step" #~ msgid "Failed to acquire mutex" #~ msgstr "Nabigo sa pag kuha ng mutex, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Nabigo sa paglagay ng characteristic, status: 0x%08lX" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "Hindi matagumpay ang paglagay ng service, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Hindi matagumpay ang paglagay ng service, status: 0x%08lX" + +#, fuzzy +#~ msgid "Failed to change softdevice state" +#~ msgstr "Nabigo sa pagbago ng softdevice state, error: 0x%08lX" + #, fuzzy #~ msgid "Failed to connect:" #~ msgstr "Hindi makaconnect, status: 0x%08lX" @@ -2837,6 +2844,10 @@ msgstr "zero step" #~ msgid "Failed to continue scanning" #~ msgstr "Hindi maituloy ang pag scan, status: 0x%0xlX" +#, fuzzy, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Hindi maituloy ang pag scan, status: 0x%0xlX" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "Hindi matagumpay ang pagbuo ng mutex, status: 0x%0xlX" @@ -2857,6 +2868,10 @@ msgstr "zero step" #~ msgid "Failed to start advertising" #~ msgstr "Hindi masimulaan ang advertisement, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Hindi masimulaan ang advertisement, status: 0x%08lX" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "Hindi masimulaan mag i-scan, status: 0x%0xlX" @@ -2865,6 +2880,10 @@ msgstr "zero step" #~ msgid "Failed to stop advertising" #~ msgstr "Hindi mahinto ang advertisement, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Hindi mahinto ang advertisement, status: 0x%08lX" + #~ msgid "Function requires lock." #~ msgstr "Kailangan ng lock ang function." @@ -3010,6 +3029,10 @@ msgstr "zero step" #~ msgstr "" #~ "nabigo ang paglalaan ng memorya, naglalaan ng %u bytes para sa native code" +#, fuzzy +#~ msgid "name must be a string" +#~ msgstr "ang keywords dapat strings" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "hindi tamang ADC Channel: %d" diff --git a/locale/fr.po b/locale/fr.po index c176fd8bcf..9136376758 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2019-04-14 20:05+0100\n" "Last-Translator: Pierrick Couturier \n" "Language-Team: fr\n" @@ -266,6 +266,10 @@ msgstr "Tous les timers pour cette broche sont utilisés" msgid "All timers in use" msgstr "Tous les timers sont utilisés" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "Fonctionnalité AnalogOut non supportée" @@ -336,6 +340,11 @@ msgstr "La luminosité doit être entre 0 et 255" msgid "Brightness not adjustable" msgstr "Luminosité non-ajustable" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -470,6 +479,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "La commande doit être un entier entre 0 et 255" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -513,7 +528,7 @@ msgstr "La broche 'Data 0' doit être aligné sur l'octet" msgid "Data chunk must follow fmt chunk" msgstr "Un bloc de données doit suivre un bloc de format" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "Données trop volumineuses pour un paquet de diffusion" @@ -560,10 +575,6 @@ msgstr "Attendu un %q" msgid "Expected a Characteristic" msgstr "Une 'Characteristic' est attendue" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -574,7 +585,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Un UUID est attendu" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -583,6 +594,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "Tuple de longueur %d attendu, obtenu %d" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -593,20 +609,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Echec de l'obtention de mutex, err 0x%04x" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Echec de l'ajout de caractéristique, err 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Echec de l'ajout de service, err 0x%04x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Echec de l'allocation du tampon RX" @@ -618,25 +628,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Echec de l'allocation de %d octets du tampon RX" #: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy -msgid "Failed to change softdevice state" -msgstr "Echec de la modification de l'état du périphérique" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, fuzzy, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Impossible de poursuivre le scan, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "Echec de la découverte de services" @@ -657,7 +664,7 @@ msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" "Impossible de notifier ou d'indiquer la valeur de l'attribut, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -666,8 +673,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Impossible de lire la valeur 'CCCD', err 0x%04x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Impossible de lire la valeur de l'attribut, err 0x%04x" @@ -687,35 +693,27 @@ msgstr "Echec de l'ajout de l'UUID du fournisseur, err 0x%04x" msgid "Failed to release mutex, err 0x%04x" msgstr "Impossible de libérer mutex, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Impossible de commencer à diffuser, err 0x%04x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Impossible de commencer à scanner, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Echec de l'arrêt de diffusion, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1022,9 +1020,8 @@ msgstr "Il n'y a plus d'espace libre sur le périphérique" msgid "No such file/directory" msgstr "Fichier/dossier introuvable" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Non connecté" @@ -1111,6 +1108,10 @@ msgstr "Ainsi que tout autre module présent sur le système de fichiers\n" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "Appuyez sur une touche pour entrer sur REPL ou CTRL-D pour recharger." @@ -1180,6 +1181,10 @@ msgstr "Le taux d'échantillonage doit être positif" msgid "Sample rate too high. It must be less than %d" msgstr "Taux d'échantillonage trop élevé. Doit être inf. à %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1194,11 +1199,6 @@ msgstr "Tranche et valeur de tailles différentes" msgid "Slices not supported" msgstr "Tranches non supportées" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "Assertion en mode 'soft-device', id: 0x%08lX, pc: 0x%08lX" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Fractionnement avec des sous-captures" @@ -2048,7 +2048,7 @@ msgstr "l'argument 2 de int() doit être >=2 et <=36" msgid "integer required" msgstr "entier requis" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2229,11 +2229,6 @@ msgstr "doit utiliser un argument nommé pour une fonction key" msgid "name '%q' is not defined" msgstr "nom '%q' non défini" -#: shared-bindings/_bleio/Peripheral.c -#, fuzzy -msgid "name must be a string" -msgstr "les noms doivent être des chaînes de caractère" - #: py/runtime.c msgid "name not defined" msgstr "nom non défini" @@ -2285,7 +2280,7 @@ msgstr "" msgid "no such attribute" msgstr "pas de tel attribut" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2783,7 +2778,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "'value_count' doit être > 0" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2873,10 +2868,22 @@ msgstr "'step' nul" #~ msgid "Failed to acquire mutex" #~ msgstr "Echec de l'obtention de mutex" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Echec de l'ajout de caractéristique, err 0x%04x" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "Echec de l'ajout de service" +#, fuzzy, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Echec de l'ajout de service, err 0x%04x" + +#, fuzzy +#~ msgid "Failed to change softdevice state" +#~ msgstr "Echec de la modification de l'état du périphérique" + #, fuzzy #~ msgid "Failed to connect:" #~ msgstr "Echec de connection:" @@ -2885,6 +2892,10 @@ msgstr "'step' nul" #~ msgid "Failed to continue scanning" #~ msgstr "Impossible de poursuivre le scan" +#, fuzzy, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Impossible de poursuivre le scan, err 0x%04x" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "Echec de la création de mutex" @@ -2905,6 +2916,10 @@ msgstr "'step' nul" #~ msgid "Failed to start advertising" #~ msgstr "Echec du démarrage de la diffusion" +#, fuzzy, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Impossible de commencer à diffuser, err 0x%04x" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "Impossible de commencer à scanner" @@ -2913,6 +2928,10 @@ msgstr "'step' nul" #~ msgid "Failed to stop advertising" #~ msgstr "Echec de l'arrêt de diffusion" +#, fuzzy, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Echec de l'arrêt de diffusion, err 0x%04x" + #~ msgid "Function requires lock." #~ msgstr "La fonction nécessite un verrou." @@ -2984,6 +3003,10 @@ msgstr "'step' nul" #~ msgid "STA required" #~ msgstr "'STA' requis" +#, c-format +#~ msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +#~ msgstr "Assertion en mode 'soft-device', id: 0x%08lX, pc: 0x%08lX" + #~ msgid "Tile indices must be 0 - 255" #~ msgstr "Les indices des tuiles doivent être compris entre 0 et 255 " @@ -3077,6 +3100,10 @@ msgstr "'step' nul" #~ msgstr "" #~ "l'allocation de mémoire a échoué en allouant %u octets pour un code natif" +#, fuzzy +#~ msgid "name must be a string" +#~ msgstr "les noms doivent être des chaînes de caractère" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "canal ADC non valide : %d" diff --git a/locale/it_IT.po b/locale/it_IT.po index 883c65d41f..d4035fdf09 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-10-02 16:27+0200\n" "Last-Translator: Enrico Paganin \n" "Language-Team: \n" @@ -262,6 +262,10 @@ msgstr "Tutti i timer per questo pin sono in uso" msgid "All timers in use" msgstr "Tutti i timer utilizzati" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "funzionalità AnalogOut non supportata" @@ -331,6 +335,11 @@ msgstr "La luminosità deve essere compreso tra 0 e 255" msgid "Brightness not adjustable" msgstr "Illiminazione non è regolabile" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -465,6 +474,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "I byte devono essere compresi tra 0 e 255" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -508,7 +523,7 @@ msgstr "graphic deve essere lunga 2048 byte" msgid "Data chunk must follow fmt chunk" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy msgid "Data too large for advertisement packet" msgstr "Impossibile inserire dati nel pacchetto di advertisement." @@ -556,10 +571,6 @@ msgstr "Atteso un %q" msgid "Expected a Characteristic" msgstr "Non è possibile aggiungere Characteristic." -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -570,7 +581,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Atteso un %q" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -579,6 +590,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -589,20 +605,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Impossibile fermare advertisement. status: 0x%02x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Impossibile fermare advertisement. status: 0x%02x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Impossibile allocare buffer RX" @@ -614,25 +624,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Fallita allocazione del buffer RX di %d byte" #: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy -msgid "Failed to change softdevice state" -msgstr "Impossibile fermare advertisement. status: 0x%02x" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, fuzzy, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Impossible iniziare la scansione. status: 0x%02x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "Impossibile fermare advertisement. status: 0x%02x" @@ -651,7 +658,7 @@ msgstr "Impossibile fermare advertisement. status: 0x%02x" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Notificamento o indicazione di attribute value fallito, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -660,8 +667,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Tentative leggere attribute value fallito, err 0x%04x" @@ -681,35 +687,27 @@ msgstr "Non è possibile aggiungere l'UUID del vendor specifico da 128-bit" msgid "Failed to release mutex, err 0x%04x" msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Impossibile avviare advertisement. status: 0x%02x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Impossible iniziare la scansione. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Impossibile fermare advertisement. status: 0x%02x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1012,9 +1010,8 @@ msgstr "Non che spazio sul dispositivo" msgid "No such file/directory" msgstr "Nessun file/directory esistente" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Impossible connettersi all'AP" @@ -1099,6 +1096,10 @@ msgstr "Imposssibile rimontare il filesystem" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1170,6 +1171,10 @@ msgid "Sample rate too high. It must be less than %d" msgstr "" "Frequenza di campionamento troppo alta. Il valore deve essere inferiore a %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1184,11 +1189,6 @@ msgstr "" msgid "Slices not supported" msgstr "Slice non supportate" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Suddivisione con sotto-catture" @@ -2008,7 +2008,7 @@ msgstr "il secondo argomanto di int() deve essere >= 2 e <= 36" msgid "integer required" msgstr "intero richiesto" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2190,11 +2190,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "nome '%q'non definito" -#: shared-bindings/_bleio/Peripheral.c -#, fuzzy -msgid "name must be a string" -msgstr "argomenti nominati devono essere stringhe" - #: py/runtime.c msgid "name not defined" msgstr "nome non definito" @@ -2246,7 +2241,7 @@ msgstr "" msgid "no such attribute" msgstr "attributo inesistente" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2739,7 +2734,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2829,10 +2824,22 @@ msgstr "zero step" #~ msgid "Failed to acquire mutex" #~ msgstr "Impossibile allocare buffer RX" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Impossibile fermare advertisement. status: 0x%02x" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "Impossibile fermare advertisement. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Impossibile fermare advertisement. status: 0x%02x" + +#, fuzzy +#~ msgid "Failed to change softdevice state" +#~ msgstr "Impossibile fermare advertisement. status: 0x%02x" + #, fuzzy #~ msgid "Failed to connect:" #~ msgstr "Impossibile connettersi. status: 0x%02x" @@ -2841,6 +2848,10 @@ msgstr "zero step" #~ msgid "Failed to continue scanning" #~ msgstr "Impossible iniziare la scansione. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Impossible iniziare la scansione. status: 0x%02x" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x" @@ -2861,6 +2872,10 @@ msgstr "zero step" #~ msgid "Failed to start advertising" #~ msgstr "Impossibile avviare advertisement. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Impossibile avviare advertisement. status: 0x%02x" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "Impossible iniziare la scansione. status: 0x%02x" @@ -2869,6 +2884,10 @@ msgstr "zero step" #~ msgid "Failed to stop advertising" #~ msgstr "Impossibile fermare advertisement. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Impossibile fermare advertisement. status: 0x%02x" + #~ msgid "GPIO16 does not support pull up." #~ msgstr "GPIO16 non supporta pull-up" @@ -3008,6 +3027,10 @@ msgstr "zero step" #~ msgstr "" #~ "allocazione di memoria fallita, allocazione di %d byte per codice nativo" +#, fuzzy +#~ msgid "name must be a string" +#~ msgstr "argomenti nominati devono essere stringhe" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "canale ADC non valido: %d" diff --git a/locale/pl.po b/locale/pl.po index 9ed76924b5..0edc5906e8 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2019-03-19 18:37-0700\n" "Last-Translator: Radomir Dopieralski \n" "Language-Team: pl\n" @@ -260,6 +260,10 @@ msgstr "Wszystkie timery tej nóżki w użyciu" msgid "All timers in use" msgstr "Wszystkie timery w użyciu" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "AnalogOut jest niewspierane" @@ -328,6 +332,11 @@ msgstr "Jasność musi być pomiędzy 0 a 255" msgid "Brightness not adjustable" msgstr "Jasność nie jest regulowana" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -458,6 +467,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "Komenda musi być int pomiędzy 0 a 255" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -500,7 +515,7 @@ msgstr "Nóżka data 0 musi być wyrównana do bajtu" msgid "Data chunk must follow fmt chunk" msgstr "Fragment danych musi następować po fragmencie fmt" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "Zbyt dużo danych pakietu rozgłoszeniowego" @@ -546,10 +561,6 @@ msgstr "Oczekiwano %q" msgid "Expected a Characteristic" msgstr "Oczekiwano charakterystyki" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -559,7 +570,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Oczekiwano UUID" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -568,6 +579,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "Oczekiwano krotkę długości %d, otrzymano %d" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -578,20 +594,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Nie udało się uzyskać blokady, błąd 0x$04x" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Nie udało się dodać charakterystyki, błąd 0x$04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Nie udało się dodać serwisu, błąd 0x%04x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Nie udała się alokacja bufora RX" @@ -603,24 +613,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Nie udała się alokacja %d bajtów na bufor RX" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" -msgstr "Nie udało się zmienić stanu softdevice" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Nie udała się kontynuacja skanowania, błąd 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "Nie udało się odkryć serwisów" @@ -637,7 +645,7 @@ msgstr "Nie udało się odczytać stanu softdevice" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Nie udało się powiadomić o wartości atrybutu, błąd 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -646,8 +654,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Nie udało się odczytać CCCD, błąd 0x%04x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Nie udało się odczytać wartości atrybutu, błąd 0x%04x" @@ -667,35 +674,27 @@ msgstr "Nie udało się zarejestrować UUID dostawcy, błąd 0x%04x" msgid "Failed to release mutex, err 0x%04x" msgstr "Nie udało się zwolnić blokady, błąd 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Nie udało się rozpocząć rozgłaszania, błąd 0x%04x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Nie udało się rozpocząć skanowania, błąd 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Nie udało się zatrzymać rozgłaszania, błąd 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -999,9 +998,8 @@ msgstr "Brak miejsca" msgid "No such file/directory" msgstr "Brak pliku/katalogu" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "Nie podłączono" @@ -1075,6 +1073,10 @@ msgstr "Oraz moduły w systemie plików\n" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "Dowolny klawisz aby uruchomić konsolę. CTRL-D aby przeładować." @@ -1141,6 +1143,10 @@ msgstr "Częstotliwość próbkowania musi być dodatnia" msgid "Sample rate too high. It must be less than %d" msgstr "Zbyt wysoka częstotliwość próbkowania. Musi być mniejsza niż %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1155,11 +1161,6 @@ msgstr "Fragment i wartość są różnych długości." msgid "Slices not supported" msgstr "Fragmenty nieobsługiwane" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "Soft device assert, id: 0x%08lX, pc: 0x%08lX" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Podział z podgrupami" @@ -1975,7 +1976,7 @@ msgstr "argument 2 do int() busi być pomiędzy 2 a 36" msgid "integer required" msgstr "wymagana liczba całkowita" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2152,10 +2153,6 @@ msgstr "funkcja key musi być podana jako argument nazwany" msgid "name '%q' is not defined" msgstr "nazwa '%q' niezdefiniowana" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "nazwa musi być łańcuchem" - #: py/runtime.c msgid "name not defined" msgstr "nazwa niezdefiniowana" @@ -2206,7 +2203,7 @@ msgstr "" msgid "no such attribute" msgstr "nie ma takiego atrybutu" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2690,7 +2687,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "value_count musi być > 0" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2749,15 +2746,30 @@ msgstr "zerowy krok" #~ msgid "Failed to acquire mutex" #~ msgstr "Nie udało się uzyskać blokady" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Nie udało się dodać charakterystyki, błąd 0x$04x" + #~ msgid "Failed to add service" #~ msgstr "Nie udało się dodać serwisu" +#, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Nie udało się dodać serwisu, błąd 0x%04x" + +#~ msgid "Failed to change softdevice state" +#~ msgstr "Nie udało się zmienić stanu softdevice" + #~ msgid "Failed to connect:" #~ msgstr "Nie udało się połączenie:" #~ msgid "Failed to continue scanning" #~ msgstr "Nie udała się kontynuacja skanowania" +#, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Nie udała się kontynuacja skanowania, błąd 0x%04x" + #~ msgid "Failed to create mutex" #~ msgstr "Nie udało się stworzyć blokady" @@ -2767,12 +2779,20 @@ msgstr "zerowy krok" #~ msgid "Failed to start advertising" #~ msgstr "Nie udało się rozpocząć rozgłaszania" +#, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Nie udało się rozpocząć rozgłaszania, błąd 0x%04x" + #~ msgid "Failed to start scanning" #~ msgstr "Nie udało się rozpocząć skanowania" #~ msgid "Failed to stop advertising" #~ msgstr "Nie udało się zatrzymać rozgłaszania" +#, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Nie udało się zatrzymać rozgłaszania, błąd 0x%04x" + #~ msgid "Invalid bit clock pin" #~ msgstr "Zła nóżka zegara" @@ -2790,6 +2810,10 @@ msgstr "zerowy krok" #~ "bpp given" #~ msgstr "Wspierane są tylko pliki BMP czarno-białe, 8bpp i 16bpp: %d bpp " +#, c-format +#~ msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +#~ msgstr "Soft device assert, id: 0x%08lX, pc: 0x%08lX" + #~ msgid "Tile indices must be 0 - 255" #~ msgstr "Indeks kafelka musi być pomiędzy 0 a 255 włącznie" @@ -2809,6 +2833,9 @@ msgstr "zerowy krok" #~ msgid "interval not in range 0.0020 to 10.24" #~ msgstr "przedział poza zakresem 0.0020 do 10.24" +#~ msgid "name must be a string" +#~ msgstr "nazwa musi być łańcuchem" + #~ msgid "services includes an object that is not a Service" #~ msgstr "obiekt typu innego niż Service w services" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index a17a275390..b5cd24405a 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-10-02 21:14-0000\n" "Last-Translator: \n" "Language-Team: \n" @@ -262,6 +262,10 @@ msgstr "Todos os temporizadores para este pino estão em uso" msgid "All timers in use" msgstr "Todos os temporizadores em uso" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "Funcionalidade AnalogOut não suportada" @@ -328,6 +332,11 @@ msgstr "O brilho deve estar entre 0 e 255" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -461,6 +470,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "Os bytes devem estar entre 0 e 255." +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -503,7 +518,7 @@ msgstr "" msgid "Data chunk must follow fmt chunk" msgstr "Pedaço de dados deve seguir o pedaço de cortes" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy msgid "Data too large for advertisement packet" msgstr "Não é possível ajustar dados no pacote de anúncios." @@ -551,10 +566,6 @@ msgstr "Esperado um" msgid "Expected a Characteristic" msgstr "Não é possível adicionar Característica." -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -565,7 +576,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Esperado um" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -574,6 +585,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "Falha ao enviar comando." @@ -584,20 +600,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Não é possível ler o valor do atributo. status: 0x%02x" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Não pode parar propaganda. status: 0x%02x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Não pode parar propaganda. status: 0x%02x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Falha ao alocar buffer RX" @@ -609,25 +619,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Falha ao alocar buffer RX de %d bytes" #: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy -msgid "Failed to change softdevice state" -msgstr "Não pode parar propaganda. status: 0x%02x" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, fuzzy, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Não é possível iniciar o anúncio. status: 0x%02x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "Não pode parar propaganda. status: 0x%02x" @@ -646,7 +653,7 @@ msgstr "Não pode parar propaganda. status: 0x%02x" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -655,8 +662,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Não é possível ler o valor do atributo. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -676,35 +682,27 @@ msgstr "Não é possível adicionar o UUID de 128 bits específico do fornecedor msgid "Failed to release mutex, err 0x%04x" msgstr "Não é possível ler o valor do atributo. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Não é possível iniciar o anúncio. status: 0x%02x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Não é possível iniciar o anúncio. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Não pode parar propaganda. status: 0x%02x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1004,9 +1002,8 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Não é possível conectar-se ao AP" @@ -1084,6 +1081,10 @@ msgstr "Não é possível remontar o sistema de arquivos" msgid "Pop from an empty Ps2 buffer" msgstr "Buffer Ps2 vazio" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1151,6 +1152,10 @@ msgstr "" msgid "Sample rate too high. It must be less than %d" msgstr "Taxa de amostragem muito alta. Deve ser menor que %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1165,11 +1170,6 @@ msgstr "" msgid "Slices not supported" msgstr "" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "" @@ -1975,7 +1975,7 @@ msgstr "" msgid "integer required" msgstr "inteiro requerido" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2152,11 +2152,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "" -#: shared-bindings/_bleio/Peripheral.c -#, fuzzy -msgid "name must be a string" -msgstr "heap deve ser uma lista" - #: py/runtime.c msgid "name not defined" msgstr "nome não definido" @@ -2207,7 +2202,7 @@ msgstr "" msgid "no such attribute" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2692,7 +2687,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2759,10 +2754,26 @@ msgstr "passo zero" #~ msgid "Failed to acquire mutex" #~ msgstr "Falha ao alocar buffer RX" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Não pode parar propaganda. status: 0x%02x" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "Não pode parar propaganda. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Não pode parar propaganda. status: 0x%02x" + +#, fuzzy +#~ msgid "Failed to change softdevice state" +#~ msgstr "Não pode parar propaganda. status: 0x%02x" + +#, fuzzy, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Não é possível iniciar o anúncio. status: 0x%02x" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "Não é possível ler o valor do atributo. status: 0x%02x" @@ -2783,6 +2794,10 @@ msgstr "passo zero" #~ msgid "Failed to start advertising" #~ msgstr "Não é possível iniciar o anúncio. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Não é possível iniciar o anúncio. status: 0x%02x" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "Não é possível iniciar o anúncio. status: 0x%02x" @@ -2791,6 +2806,10 @@ msgstr "passo zero" #~ msgid "Failed to stop advertising" #~ msgstr "Não pode parar propaganda. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Não pode parar propaganda. status: 0x%02x" + #~ msgid "GPIO16 does not support pull up." #~ msgstr "GPIO16 não suporta pull up." @@ -2921,6 +2940,10 @@ msgstr "passo zero" #~ msgid "memory allocation failed, allocating %u bytes for native code" #~ msgstr "alocação de memória falhou, alocando %u bytes para código nativo" +#, fuzzy +#~ msgid "name must be a string" +#~ msgstr "heap deve ser uma lista" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "não é um canal ADC válido: %d" diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index d5df0b7b0c..dfd7e8b0db 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: circuitpython-cn\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2019-04-13 10:10-0700\n" "Last-Translator: hexthat\n" "Language-Team: Chinese Hanyu Pinyin\n" @@ -261,6 +261,10 @@ msgstr "Cǐ yǐn jiǎo de suǒyǒu jìshí qì zhèngzài shǐyòng" msgid "All timers in use" msgstr "Suǒyǒu jìshí qì shǐyòng" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "Bù zhīchí AnalogOut gōngnéng" @@ -329,6 +333,11 @@ msgstr "Liàngdù bìxū jiè yú 0 dào 255 zhī jiān" msgid "Brightness not adjustable" msgstr "Liàngdù wúfǎ tiáozhěng" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -459,6 +468,12 @@ msgstr "Mìnglìng bìxū wèi 0-255" msgid "Command must be an int between 0 and 255" msgstr "Mìnglìng bìxū shì 0 dào 255 zhī jiān de int" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Fǔbài de .mpy wénjiàn" @@ -501,7 +516,7 @@ msgstr "Shùjù 0 de yǐn jiǎo bìxū shì zì jié duìqí" msgid "Data chunk must follow fmt chunk" msgstr "Shùjù kuài bìxū zūnxún fmt qū kuài" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "Guǎnggào bāo de shùjù tài dà" @@ -547,10 +562,6 @@ msgstr "Yùqí %q" msgid "Expected a Characteristic" msgstr "Yùqí de tèdiǎn" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "Qídài yīgè wàiwéi shèbèi" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Yùqí fúwù" @@ -560,7 +571,7 @@ msgstr "Yùqí fúwù" msgid "Expected a UUID" msgstr "Yùqí UUID" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "Qídài yīgè dìzhǐ" @@ -569,6 +580,11 @@ msgstr "Qídài yīgè dìzhǐ" msgid "Expected tuple of length %d, got %d" msgstr "Qīwàng de chángdù wèi %d de yuán zǔ, dédào %d" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "Fāsòng mìnglìng shībài." @@ -579,20 +595,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Wúfǎ huòdé mutex, err 0x%04x" #: ports/nrf/common-hal/_bleio/Service.c -#, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Tiānjiā tèxìng shībài, err 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "Wúfǎ tiānjiā miáoshù fú, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Tiānjiā fúwù shībài, err 0x%04x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Fēnpèi RX huǎnchōng shībài" @@ -604,24 +614,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Fēnpèi RX huǎnchōng qū%d zì jié shībài" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" -msgstr "Gēnggǎi ruǎn shèbèi zhuàngtài shībài" +msgid "Failed to change softdevice state, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" -msgstr "Wúfǎ pèizhì guǎnggào, cuòwù 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "Liánjiē shībài: Chāoshí" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Jìxù sǎomiáo shībài, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "Fāxiàn fúwù shībài" @@ -638,7 +646,7 @@ msgstr "Wúfǎ huòdé ruǎnjiàn shèbèi zhuàngtài" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Wúfǎ tōngzhī huò xiǎnshì shǔxìng zhí, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "Pèiduì shībài" @@ -647,8 +655,7 @@ msgstr "Pèiduì shībài" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Dòu qǔ CCCD zhí, err 0x%04x shībài" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Dòu qǔ shǔxìng zhí shībài, err 0x%04x" @@ -668,35 +675,27 @@ msgstr "Wúfǎ zhùcè màizhǔ tèdìng de UUID, err 0x%04x" msgid "Failed to release mutex, err 0x%04x" msgstr "Wúfǎ shìfàng mutex, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" -msgstr "Wúfǎ shèzhì shèbèi míngchēng, cuòwù 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Qǐdòng guǎnggào shībài, err 0x%04x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "Wúfǎ kāishǐ liánjiē, cuòwù 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" -msgstr "Wúfǎ kāishǐ pèiduì, cuòwù 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Qǐdòng sǎomiáo shībài, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Wúfǎ tíngzhǐ guǎnggào, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -999,9 +998,8 @@ msgstr "Shèbèi shàng méiyǒu kònggé" msgid "No such file/directory" msgstr "Méiyǒu cǐ lèi wénjiàn/mùlù" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "Wèi liánjiē" @@ -1079,6 +1077,10 @@ msgstr "Zài wénjiàn xìtǒng shàng tiānjiā rènhé mókuài\n" msgid "Pop from an empty Ps2 buffer" msgstr "Cóng kōng de Ps2 huǎnchōng qū dànchū" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "Àn xià rènhé jiàn jìnrù REPL. Shǐyòng CTRL-D chóngxīn jiāzài." @@ -1145,6 +1147,10 @@ msgstr "Cǎiyàng lǜ bìxū wèi zhèng shù" msgid "Sample rate too high. It must be less than %d" msgstr "Cǎiyàng lǜ tài gāo. Tā bìxū xiǎoyú %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1159,11 +1165,6 @@ msgstr "Qiēpiàn hé zhí bùtóng chángdù." msgid "Slices not supported" msgstr "Qiēpiàn bù shòu zhīchí" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "Ruǎn shèbèi wéihù, id: 0X%08lX, pc: 0X%08lX" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Yǔ zi bǔhuò fēnliè" @@ -1986,7 +1987,7 @@ msgstr "zhěngshù() cānshù 2 bìxū > = 2 qiě <= 36" msgid "integer required" msgstr "xūyào zhěngshù" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "Jiàngé bìxū zài %s-%s fànwéi nèi" @@ -2164,10 +2165,6 @@ msgstr "bìxū shǐyòng guānjiàn cí cānshù" msgid "name '%q' is not defined" msgstr "míngchēng '%q' wèi dìngyì" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "míngchēng bìxū shì yīgè zìfú chuàn" - #: py/runtime.c msgid "name not defined" msgstr "míngchēng wèi dìngyì" @@ -2219,7 +2216,7 @@ msgstr "Méiyǒu kěyòng de fùwèi yǐn jiǎo" msgid "no such attribute" msgstr "méiyǒu cǐ shǔxìng" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "Zài service_uuids bái míngdān zhōng zhǎodào fēi UUID" @@ -2703,7 +2700,7 @@ msgstr "Zhí bìxū fúhé %d zì jié" msgid "value_count must be > 0" msgstr "zhí jìshù bìxū wèi > 0" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "Chuāngkǒu bìxū shì <= jiàngé" @@ -2762,33 +2759,71 @@ msgstr "líng bù" #~ msgid "Data too large for the advertisement packet" #~ msgstr "Guǎnggào bāo de shùjù tài dà" +#~ msgid "Expected a Peripheral" +#~ msgstr "Qídài yīgè wàiwéi shèbèi" + #~ msgid "Failed to acquire mutex" #~ msgstr "Wúfǎ huòdé mutex" +#, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Tiānjiā tèxìng shībài, err 0x%04x" + #~ msgid "Failed to add service" #~ msgstr "Tiānjiā fúwù shībài" +#, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Tiānjiā fúwù shībài, err 0x%04x" + +#~ msgid "Failed to change softdevice state" +#~ msgstr "Gēnggǎi ruǎn shèbèi zhuàngtài shībài" + +#, c-format +#~ msgid "Failed to configure advertising, err 0x%04x" +#~ msgstr "Wúfǎ pèizhì guǎnggào, cuòwù 0x%04x" + #~ msgid "Failed to connect:" #~ msgstr "Liánjiē shībài:" #~ msgid "Failed to continue scanning" #~ msgstr "Jìxù sǎomiáo shībài" +#, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Jìxù sǎomiáo shībài, err 0x%04x" + #~ msgid "Failed to create mutex" #~ msgstr "Wúfǎ chuàngjiàn hù chì suǒ" #~ msgid "Failed to release mutex" #~ msgstr "Wúfǎ shìfàng mutex" +#, c-format +#~ msgid "Failed to set device name, err 0x%04x" +#~ msgstr "Wúfǎ shèzhì shèbèi míngchēng, cuòwù 0x%04x" + #~ msgid "Failed to start advertising" #~ msgstr "Qǐdòng guǎnggào shībài" +#, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Qǐdòng guǎnggào shībài, err 0x%04x" + +#, c-format +#~ msgid "Failed to start pairing, error 0x%04x" +#~ msgstr "Wúfǎ kāishǐ pèiduì, cuòwù 0x%04x" + #~ msgid "Failed to start scanning" #~ msgstr "Qǐdòng sǎomiáo shībài" #~ msgid "Failed to stop advertising" #~ msgstr "Wúfǎ tíngzhǐ guǎnggào" +#, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Wúfǎ tíngzhǐ guǎnggào, err 0x%04x" + #~ msgid "Invalid bit clock pin" #~ msgstr "Wúxiào de wèi shízhōng yǐn jiǎo" @@ -2819,6 +2854,10 @@ msgstr "líng bù" #~ msgstr "" #~ "Jǐn zhīchí dān sè, suǒyǐn 8bpp hé 16bpp huò gèng dà de BMP: %d bpp tígōng" +#, c-format +#~ msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +#~ msgstr "Ruǎn shèbèi wéihù, id: 0X%08lX, pc: 0X%08lX" + #~ msgid "Tile indices must be 0 - 255" #~ msgstr "Píng pū zhǐshù bìxū wèi 0 - 255" @@ -2840,6 +2879,9 @@ msgstr "líng bù" #~ msgid "interval not in range 0.0020 to 10.24" #~ msgstr "jùlí 0.0020 Zhì 10.24 Zhī jiān de jiàngé shíjiān" +#~ msgid "name must be a string" +#~ msgstr "míngchēng bìxū shì yīgè zìfú chuàn" + #~ msgid "row must be packed and word aligned" #~ msgstr "xíng bìxū dǎbāo bìngqiě zì duìqí" From ca4b7f81e5d040afa32fc51d7323865f5966239f Mon Sep 17 00:00:00 2001 From: Hierophect Date: Tue, 22 Oct 2019 11:09:46 -0400 Subject: [PATCH 03/38] Initial template setup --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 73 +++++++++++++++++++ ports/stm32f4/common-hal/pulseio/PWMOut.h | 43 +++++++++++ ports/stm32f4/common-hal/pulseio/PulseIn.c | 79 +++++++++++++++++++++ ports/stm32f4/common-hal/pulseio/PulseIn.h | 53 ++++++++++++++ ports/stm32f4/common-hal/pulseio/PulseOut.c | 55 ++++++++++++++ ports/stm32f4/common-hal/pulseio/PulseOut.h | 42 +++++++++++ ports/stm32f4/common-hal/pulseio/__init__.c | 1 + 7 files changed, 346 insertions(+) create mode 100644 ports/stm32f4/common-hal/pulseio/PWMOut.c create mode 100644 ports/stm32f4/common-hal/pulseio/PWMOut.h create mode 100644 ports/stm32f4/common-hal/pulseio/PulseIn.c create mode 100644 ports/stm32f4/common-hal/pulseio/PulseIn.h create mode 100644 ports/stm32f4/common-hal/pulseio/PulseOut.c create mode 100644 ports/stm32f4/common-hal/pulseio/PulseOut.h create mode 100644 ports/stm32f4/common-hal/pulseio/__init__.c diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c new file mode 100644 index 0000000000..f3c0a945bc --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -0,0 +1,73 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include "py/runtime.h" +#include "common-hal/pulseio/PWMOut.h" +#include "shared-bindings/pulseio/PWMOut.h" +#include "supervisor/shared/translate.h" + +void pwmout_reset(void) { +} + +void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self) { +} + +void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self) { +} + +pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, + const mcu_pin_obj_t* pin, + uint16_t duty, + uint32_t frequency, + bool variable_frequency) { + return PWMOUT_OK; +} + +bool common_hal_pulseio_pwmout_deinited(pulseio_pwmout_obj_t* self) { + return true; +} + +void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { +} + +void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) { +} + +uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { + return 0; +} + +void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency) { +} + +uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) { + return 0; +} + +bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) { + return 0; +} diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.h b/ports/stm32f4/common-hal/pulseio/PWMOut.h new file mode 100644 index 0000000000..58adb196c8 --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.h @@ -0,0 +1,43 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H +#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + uint8_t pin_number; + uint8_t channel: 7; + bool variable_frequency: 1; + uint16_t duty_cycle; + uint32_t frequency; +} pulseio_pwmout_obj_t; + +void pwmout_reset(void); + +#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H diff --git a/ports/stm32f4/common-hal/pulseio/PulseIn.c b/ports/stm32f4/common-hal/pulseio/PulseIn.c new file mode 100644 index 0000000000..25adb7d769 --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/PulseIn.c @@ -0,0 +1,79 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "common-hal/pulseio/PulseIn.h" +#include +#include +#include "py/mpconfig.h" +#include "py/gc.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/pulseio/PulseIn.h" +#include "tick.h" + +void pulsein_reset(void) { +} + +void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin, + uint16_t maxlen, bool idle_state) { + mp_raise_NotImplementedError(translate("PulseIn not yet supported")); +} + +bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) { + return true; +} + +void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) { +} + +void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) { +} + +void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint16_t trigger_duration) { +} + +void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) { +} + +uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) { + return 0; +} + +uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) { + return 0; +} + +uint16_t common_hal_pulseio_pulsein_get_maxlen(pulseio_pulsein_obj_t* self) { + return 0; +} + +bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t* self) { + return 0; +} + +uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self) { + return 0; +} diff --git a/ports/stm32f4/common-hal/pulseio/PulseIn.h b/ports/stm32f4/common-hal/pulseio/PulseIn.h new file mode 100644 index 0000000000..9f4cc9f43c --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/PulseIn.h @@ -0,0 +1,53 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PULSEIN_H +#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PULSEIN_H + +#include "common-hal/microcontroller/Pin.h" + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + + uint8_t pin; + bool idle_state; + bool paused; + volatile bool first_edge; + + uint16_t* buffer; + uint16_t maxlen; + + volatile uint16_t start; + volatile uint16_t len; + volatile uint16_t last_us; + volatile uint64_t last_ms; +} pulseio_pulsein_obj_t; + +void pulsein_reset(void); + +#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PULSEIN_H diff --git a/ports/stm32f4/common-hal/pulseio/PulseOut.c b/ports/stm32f4/common-hal/pulseio/PulseOut.c new file mode 100644 index 0000000000..7e9812db69 --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/PulseOut.c @@ -0,0 +1,55 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "common-hal/pulseio/PulseOut.h" + +#include + +#include "py/mpconfig.h" +#include "py/gc.h" +#include "py/runtime.h" +#include "shared-bindings/pulseio/PulseOut.h" +#include "shared-bindings/pulseio/PWMOut.h" +#include "supervisor/shared/translate.h" + + +void pulseout_reset() { +} + +void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self, + const pulseio_pwmout_obj_t* carrier) { + mp_raise_NotImplementedError(translate("PulseOut not yet supported")); +} + +bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) { + return true; +} + +void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self) { +} + +void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pulses, uint16_t length) { +} diff --git a/ports/stm32f4/common-hal/pulseio/PulseOut.h b/ports/stm32f4/common-hal/pulseio/PulseOut.h new file mode 100644 index 0000000000..48f2bb3f1b --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/PulseOut.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PULSEOUT_H +#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PULSEOUT_H + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/pulseio/PWMOut.h" + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + const pulseio_pwmout_obj_t *pwmout; +} pulseio_pulseout_obj_t; + +void pulseout_reset(void); + +#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PULSEOUT_H diff --git a/ports/stm32f4/common-hal/pulseio/__init__.c b/ports/stm32f4/common-hal/pulseio/__init__.c new file mode 100644 index 0000000000..2bee925bc7 --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/__init__.c @@ -0,0 +1 @@ +// No pulseio module functions. From 1d8a75fa3f6354bd6cd44a8de961650ff064093d Mon Sep 17 00:00:00 2001 From: Hierophect Date: Tue, 22 Oct 2019 13:11:45 -0400 Subject: [PATCH 04/38] minor WIP --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index f3c0a945bc..78f7b212d7 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -44,6 +44,29 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, uint16_t duty, uint32_t frequency, bool variable_frequency) { + + __HAL_RCC_TIM4_CLK_ENABLE(); + + TIM_HandleTypeDef tim = {0}; + tim.Instance = TIM4; + tim.Init.Period = LED_PWM_TIM_PERIOD - 1; + tim.Init.Prescaler = timer_get_source_freq(pwm_cfg->tim_id) / 1000000 - 1; // TIM runs at 1MHz + tim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + tim.Init.CounterMode = TIM_COUNTERMODE_UP; + tim.Init.RepetitionCounter = 0; + HAL_TIM_PWM_Init(&tim); + + // PWM configuration + TIM_OC_InitTypeDef oc_init; + oc_init.OCMode = TIM_OCMODE_PWM1; + oc_init.Pulse = 0; // off + oc_init.OCPolarity = MICROPY_HW_LED_INVERTED ? TIM_OCPOLARITY_LOW : TIM_OCPOLARITY_HIGH; + oc_init.OCFastMode = TIM_OCFAST_DISABLE; + oc_init.OCNPolarity = TIM_OCNPOLARITY_HIGH; // needed for TIM1 and TIM8 + oc_init.OCIdleState = TIM_OCIDLESTATE_SET; // needed for TIM1 and TIM8 + oc_init.OCNIdleState = TIM_OCNIDLESTATE_SET; // needed for TIM1 and TIM8 + HAL_TIM_PWM_ConfigChannel(&tim, &oc_init, pwm_cfg->tim_channel); + HAL_TIM_PWM_Start(&tim, pwm_cfg->tim_channel); return PWMOUT_OK; } From ece8352126e34c5437080e9343f469f2f5e1bfe9 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 22 Oct 2019 17:24:04 -0700 Subject: [PATCH 05/38] Fix build by removing unused vars --- shared-module/_bleio/ScanResults.c | 5 +++-- supervisor/shared/bluetooth.c | 19 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/shared-module/_bleio/ScanResults.c b/shared-module/_bleio/ScanResults.c index 9f23a836ce..7ea0c165f4 100644 --- a/shared-module/_bleio/ScanResults.c +++ b/shared-module/_bleio/ScanResults.c @@ -28,6 +28,7 @@ #include +#include "lib/utils/interrupt_char.h" #include "py/objstr.h" #include "py/runtime.h" #include "shared-bindings/_bleio/ScanEntry.h" @@ -44,10 +45,10 @@ bleio_scanresults_obj_t* shared_module_bleio_new_scanresults(size_t buffer_size, } mp_obj_t common_hal_bleio_scanresults_next(bleio_scanresults_obj_t *self) { - while (ringbuf_count(&self->buf) == 0 && !self->done && !mp_exception_pending()) { + while (ringbuf_count(&self->buf) == 0 && !self->done && !mp_hal_is_interrupted()) { RUN_BACKGROUND_TASKS; } - if (ringbuf_count(&self->buf) == 0 || mp_exception_pending()) { + if (ringbuf_count(&self->buf) == 0 || mp_hal_is_interrupted()) { return mp_const_none; } diff --git a/supervisor/shared/bluetooth.c b/supervisor/shared/bluetooth.c index 64f3b55eb6..02258de742 100644 --- a/supervisor/shared/bluetooth.c +++ b/supervisor/shared/bluetooth.c @@ -87,7 +87,7 @@ void supervisor_start_bluetooth(void) { characteristic_list.items = characteristic_list_items; mp_seq_clear(characteristic_list.items, 0, characteristic_list.alloc, sizeof(*characteristic_list.items)); - const uint32_t err_code = _common_hal_bleio_service_construct(&supervisor_ble_service, &supervisor_ble_service_uuid, false /* is secondary */, &characteristic_list); + _common_hal_bleio_service_construct(&supervisor_ble_service, &supervisor_ble_service_uuid, false /* is secondary */, &characteristic_list); // File length supervisor_ble_version_uuid.base.type = &bleio_uuid_type; @@ -186,7 +186,7 @@ void open_current_file(void) { path[length] = '\0'; FATFS *fs = &((fs_user_mount_t *) MP_STATE_VM(vfs_mount_table)->obj)->fatfs; - FRESULT result = f_open(fs, &active_file, (char*) path, FA_READ | FA_WRITE); + f_open(fs, &active_file, (char*) path, FA_READ | FA_WRITE); update_file_length(); } @@ -246,7 +246,6 @@ void supervisor_bluetooth_background(void) { //uint32_t data_shift_length = fileLength - offset - remove_length; int32_t data_shift = insert_length - remove_length; uint32_t new_length = file_length + data_shift; - FRESULT result; // TODO: Make these loops smarter to read and write on sector boundaries. if (data_shift < 0) { @@ -254,32 +253,32 @@ void supervisor_bluetooth_background(void) { uint8_t data; UINT actual; f_lseek(&active_file, shift_offset - data_shift); - result = f_read(&active_file, &data, 1, &actual); + f_read(&active_file, &data, 1, &actual); f_lseek(&active_file, shift_offset); - result = f_write(&active_file, &data, 1, &actual); + f_write(&active_file, &data, 1, &actual); } f_truncate(&active_file); } else if (data_shift > 0) { - result = f_lseek(&active_file, file_length); + f_lseek(&active_file, file_length); // Fill end with 0xff so we don't need to erase. uint8_t data = 0xff; for (size_t i = 0; i < (size_t) data_shift; i++) { UINT actual; - result = f_write(&active_file, &data, 1, &actual); + f_write(&active_file, &data, 1, &actual); } for (uint32_t shift_offset = new_length - 1; shift_offset >= offset + insert_length ; shift_offset--) { UINT actual; f_lseek(&active_file, shift_offset - data_shift); - result = f_read(&active_file, &data, 1, &actual); + f_read(&active_file, &data, 1, &actual); f_lseek(&active_file, shift_offset); - result = f_write(&active_file, &data, 1, &actual); + f_write(&active_file, &data, 1, &actual); } } f_lseek(&active_file, offset); uint8_t* data = (uint8_t *) (current_command + 4); UINT written; - result = f_write(&active_file, data, insert_length, &written); + f_write(&active_file, data, insert_length, &written); f_sync(&active_file); // Notify the new file length. update_file_length(); From 91c9d519ae74923eec7f95dd606f83555a21f751 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 22 Oct 2019 23:09:56 -0700 Subject: [PATCH 06/38] Refine comments and switch prefix_len to size_t --- ports/nrf/common-hal/_bleio/Adapter.c | 7 ++++--- shared-bindings/_bleio/Adapter.c | 6 +++--- shared-bindings/_bleio/Adapter.h | 2 +- shared-bindings/_bleio/Service.c | 6 +++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index 41189a86df..295a42d63b 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -123,7 +123,7 @@ STATIC uint32_t ble_stack_enable(void) { return err_code; } - // Double the GATT Server attribute size to accomodate both the CircuitPython built-in service + // Triple the GATT Server attribute size to accomodate both the CircuitPython built-in service // and anything the user does. memset(&ble_conf, 0, sizeof(ble_conf)); ble_conf.gatts_cfg.attr_tab_size.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT * 3; @@ -163,7 +163,8 @@ STATIC bool adapter_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { switch (ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: { - // Find an empty connection + // Find an empty connection. One must always be available because the SD has the same + // total connection limit. bleio_connection_internal_t *connection; for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { connection = &connections[i]; @@ -369,7 +370,7 @@ STATIC bool scan_on_ble_evt(ble_evt_t *ble_evt, void *scan_results_in) { return true; } -mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, uint8_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active) { +mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active) { if (self->scan_results != NULL) { if (!shared_module_bleio_scanresults_get_done(self->scan_results)) { mp_raise_RuntimeError(translate("Scan already in progess. Stop with stop_scan.")); diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index 01dba04919..a64167e5a7 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -61,8 +61,8 @@ //| additional functionality available after the devices establish a connection. For example, a //| BLE keyboard may advertise that it can provide key information, but not what the key info is. //| -//| The built-in BLE adapter can do both parts of this process, it can scan for other device -//| advertisements and it can advertise it's own data. Furthermore, Adapters can accept incoming +//| The built-in BLE adapter can do both parts of this process: it can scan for other device +//| advertisements and it can advertise its own data. Furthermore, Adapters can accept incoming //| connections and also initiate connections. //| @@ -207,7 +207,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_advertising_obj, bleio_adapt //| filtered and returned separately. //| //| :param sequence prefixes: Sequence of byte string prefixes to filter advertising packets -//| with. A packets without an advertising structure that matches one of the prefixes are +//| with. A packet without an advertising structure that matches one of the prefixes is //| ignored. Format is one byte for length (n) and n bytes of prefix and can be repeated. //| :param int buffer_size: the maximum number of advertising bytes to buffer. //| :param bool extended: When True, support extended advertising packets. Increasing buffer_size is recommended when this is set. diff --git a/shared-bindings/_bleio/Adapter.h b/shared-bindings/_bleio/Adapter.h index 95d19cb319..2ff77f755b 100644 --- a/shared-bindings/_bleio/Adapter.h +++ b/shared-bindings/_bleio/Adapter.h @@ -50,7 +50,7 @@ extern uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t extern void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo); void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self); -mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, uint8_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active); +mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active); void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self); bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self); diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c index 68605cec00..52dea592e4 100644 --- a/shared-bindings/_bleio/Service.c +++ b/shared-bindings/_bleio/Service.c @@ -45,10 +45,10 @@ //| connections. This is known as a Service server. Client Service objects are created via //| `Connection.discover_remote_services`. //| -//| To mark the Server as secondary, pass `True` as :py:data:`secondary`. +//| To mark the Service as secondary, pass `True` as :py:data:`secondary`. //| -//| :param UUID uuid: The uuid of the server -//| :param bool secondary: If the server is a secondary one +//| :param UUID uuid: The uuid of the service +//| :param bool secondary: If the service is a secondary one // //| :return: the new Service //| From 4fdf518251dd0751cf4e9b06b7ffb2b944e7d15c Mon Sep 17 00:00:00 2001 From: Thea Flowers Date: Tue, 22 Oct 2019 10:37:36 -0700 Subject: [PATCH 07/38] Track unadjusted PWM duty cycle to avoid accumulating conversion errors Fixes #2086 When the frequency of a `PWMOut` is change it re-sets the PWM's duty cycle as well, since the registers have to be re-calculated based on the new frequency. Unfortunately, `common_hal_pulseio_pwmout_get_duty_cycle` will return a value very close to, but not exactly, the value passed to `common_hal_pulseio_pwmout_set_duty_cycle`. If the frequency is modified without the calling code also re-setting the duty cycle then the duty cycle will decay over time. This fixes that problem by tracking the unadjusted duty cycle and re-setting the duty cycle to that value when the frequency is changed. --- ports/atmel-samd/common-hal/pulseio/PWMOut.c | 11 +++++++++-- ports/atmel-samd/common-hal/pulseio/PWMOut.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.c b/ports/atmel-samd/common-hal/pulseio/PWMOut.c index 6dcace21fd..92305161f4 100644 --- a/ports/atmel-samd/common-hal/pulseio/PWMOut.c +++ b/ports/atmel-samd/common-hal/pulseio/PWMOut.c @@ -135,6 +135,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, bool variable_frequency) { self->pin = pin; self->variable_frequency = variable_frequency; + self->duty_cycle = duty; if (pin->timer[0].index >= TC_INST_NUM && pin->timer[1].index >= TCC_INST_NUM @@ -322,6 +323,13 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { } extern void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty) { + // Store the unadjusted duty cycle. It turns out the the process of adjusting and calucating + // the duty cycle here and reading it back is lossy - the value will decay over time. + // Track it here so that if frequency is changed we can use this value to recalcuate the + // proper duty cycle. + // See https://github.com/adafruit/circuitpython/issues/2086 for more details + self->duty_cycle = duty; + const pin_timer_t* t = self->timer; if (t->is_tc) { uint16_t adjusted_duty = tc_periods[t->index] * duty / 0xffff; @@ -415,7 +423,6 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, break; } } - uint16_t old_duty = common_hal_pulseio_pwmout_get_duty_cycle(self); if (t->is_tc) { Tc* tc = tc_insts[t->index]; uint8_t old_divisor = tc->COUNT16.CTRLA.bit.PRESCALER; @@ -450,7 +457,7 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, #endif } - common_hal_pulseio_pwmout_set_duty_cycle(self, old_duty); + common_hal_pulseio_pwmout_set_duty_cycle(self, self->duty_cycle); } uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) { diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.h b/ports/atmel-samd/common-hal/pulseio/PWMOut.h index eef653bcb2..09abda8196 100644 --- a/ports/atmel-samd/common-hal/pulseio/PWMOut.h +++ b/ports/atmel-samd/common-hal/pulseio/PWMOut.h @@ -36,6 +36,7 @@ typedef struct { const mcu_pin_obj_t *pin; const pin_timer_t* timer; bool variable_frequency; + uint16_t duty_cycle; } pulseio_pwmout_obj_t; void pwmout_reset(void); From 4a55c48dbf5fea9368272006f4a149e01ddaf06e Mon Sep 17 00:00:00 2001 From: Thea Flowers Date: Wed, 23 Oct 2019 15:46:14 -0700 Subject: [PATCH 08/38] Improve documentation for `rtc`. - Add examples for `rtc.RTC.datetime`. - Add type for `rtc.RTC.calibration`. - Expand on use cases for `rtc.set_time_source`. --- shared-bindings/rtc/RTC.c | 23 ++++++++++++++++++++--- shared-bindings/rtc/__init__.c | 16 ++++++++-------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/shared-bindings/rtc/RTC.c b/shared-bindings/rtc/RTC.c index 17dccdb03c..3ff09a4ec5 100644 --- a/shared-bindings/rtc/RTC.c +++ b/shared-bindings/rtc/RTC.c @@ -57,7 +57,23 @@ STATIC mp_obj_t rtc_rtc_make_new(const mp_obj_type_t *type, size_t n_args, const //| .. attribute:: datetime //| -//| The date and time of the RTC. +//| The current date and time of the RTC as a `time.struct_time`. +//| +//| This must be set to the current date and time whenever the board loses power:: +//| +//| import rtc +//| import time +//| +//| r = rtc.RTC() +//| r.datetime = rtctime.struct_time((2019, 5, 29, 15, 14, 15, 0, -1, -1)) +//| +//| +//| Once set, the RTC will automatically update this value as time passes. You can read this +//| property to get a snapshot of the current time:: +//| +//| current_time = r.datetime +//| print(current_time) +//| # struct_time(tm_year=2019, tm_month=5, ...) //| STATIC mp_obj_t rtc_rtc_obj_get_datetime(mp_obj_t self_in) { timeutils_struct_time_t tm; @@ -83,9 +99,10 @@ const mp_obj_property_t rtc_rtc_datetime_obj = { //| .. attribute:: calibration //| -//| The RTC calibration value. +//| The RTC calibration value as an `int`. +//| //| A positive value speeds up the clock and a negative value slows it down. -//| Range and value is hardware specific, but one step is often approx. 1 ppm. +//| Range and value is hardware specific, but one step is often approximately 1 ppm. //| STATIC mp_obj_t rtc_rtc_obj_get_calibration(mp_obj_t self_in) { int calibration = common_hal_rtc_get_calibration(); diff --git a/shared-bindings/rtc/__init__.c b/shared-bindings/rtc/__init__.c index ac67a7131c..22eda9b663 100644 --- a/shared-bindings/rtc/__init__.c +++ b/shared-bindings/rtc/__init__.c @@ -36,12 +36,13 @@ //| //| .. module:: rtc //| :synopsis: Real Time Clock -//| :platform: SAMD21 +//| :platform: SAMD21, SAMD51, nRF52 //| -//| The `rtc` module provides support for a Real Time Clock. -//| It also backs the `time.time()` and `time.localtime()` functions using the onboard RTC if present. +//| The `rtc` module provides support for a Real Time Clock. You can access and manage the +//| RTC using :class:`rtc.RTC`. It also backs the :func:`time.time` and :func:`time.localtime` +//| functions using the onboard RTC if present. //| -//| Libraries +//| Classes //| //| .. toctree:: //| :maxdepth: 3 @@ -63,10 +64,9 @@ mp_obj_t rtc_get_time_source_time(void) { //| .. function:: set_time_source(rtc) //| -//| Sets the rtc time source used by time.localtime(). -//| The default is `rtc.RTC()`. -//| -//| Example usage:: +//| Sets the RTC time source used by :func:`time.localtime`. +//| The default is :class:`rtc.RTC`, but it's useful to use this to override the +//| time source for testing purposes. For example:: //| //| import rtc //| import time From 64337775f818648b59a1ad9c02dda7dc6098d289 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Thu, 24 Oct 2019 12:43:34 -0400 Subject: [PATCH 09/38] PWM Base functionality testing for F405 --- ports/stm32f4/Makefile | 2 +- .../boards/feather_f405/stm32f4xx_hal_conf.h | 2 +- ports/stm32f4/common-hal/pulseio/PWMOut.c | 75 ++++++++++++++++--- ports/stm32f4/mpconfigport.mk | 1 + 4 files changed, 68 insertions(+), 12 deletions(-) diff --git a/ports/stm32f4/Makefile b/ports/stm32f4/Makefile index 4b660f244f..2727ea954f 100755 --- a/ports/stm32f4/Makefile +++ b/ports/stm32f4/Makefile @@ -121,7 +121,7 @@ LIBS += -lm endif # TinyUSB defines -CFLAGS += -DHSE_VALUE=8000000 -DCFG_TUSB_MCU=OPT_MCU_STM32F4 -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024 -DCFG_TUD_MSC_BUFSIZE=4096 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_MIDI_TX_BUFSIZE=128 +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_STM32F4 -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024 -DCFG_TUD_MSC_BUFSIZE=4096 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_MIDI_TX_BUFSIZE=128 ###################################### diff --git a/ports/stm32f4/boards/feather_f405/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/feather_f405/stm32f4xx_hal_conf.h index a13e5ecfa3..7a1a9428f8 100644 --- a/ports/stm32f4/boards/feather_f405/stm32f4xx_hal_conf.h +++ b/ports/stm32f4/boards/feather_f405/stm32f4xx_hal_conf.h @@ -61,7 +61,7 @@ /* #define HAL_SD_MODULE_ENABLED */ /* #define HAL_MMC_MODULE_ENABLED */ #define HAL_SPI_MODULE_ENABLED -/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED /* #define HAL_USART_MODULE_ENABLED */ /* #define HAL_IRDA_MODULE_ENABLED */ diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index 78f7b212d7..ba5fc06c1d 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -4,6 +4,8 @@ * The MIT License (MIT) * * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2019 Lucian Copeland for Adafruit Industries + * Utilizes code from Micropython, Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,6 +31,32 @@ #include "common-hal/pulseio/PWMOut.h" #include "shared-bindings/pulseio/PWMOut.h" #include "supervisor/shared/translate.h" +#include "stm32f4xx_hal.h" + +#define PWM_MAX_FREQ 1000000 + +// Get the frequency (in Hz) of the source clock for the given timer. +// On STM32F405/407/415/417 there are 2 cases for how the clock freq is set. +// If the APB prescaler is 1, then the timer clock is equal to its respective +// APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its +// respective APB clock. See DM00031020 Rev 4, page 115. +static uint32_t timer_get_source_freq(uint32_t tim_id) { + uint32_t source, clk_div; + if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) { + // TIM{1,8,9,10,11} are on APB2 + source = HAL_RCC_GetPCLK2Freq(); + clk_div = RCC->CFGR & RCC_CFGR_PPRE2; + } else { + // TIM{2,3,4,5,6,7,12,13,14} are on APB1 + source = HAL_RCC_GetPCLK1Freq(); + clk_div = RCC->CFGR & RCC_CFGR_PPRE1; + } + if (clk_div != 0) { + // APB prescaler for this timer is > 1 + source *= 2; + } + return source; +} void pwmout_reset(void) { } @@ -44,29 +72,56 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, uint16_t duty, uint32_t frequency, bool variable_frequency) { + //Using PB08: Tim4 Ch3 for testing + int tim_num = 10; + int tim_chan = TIM_CHANNEL_1; - __HAL_RCC_TIM4_CLK_ENABLE(); + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = pin_mask(pin->number); + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = 3;//2; //2 is timer 4 + HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct); + + //__HAL_RCC_TIM4_CLK_ENABLE(); + __HAL_RCC_TIM10_CLK_ENABLE(); + + uint32_t source_freq = timer_get_source_freq(tim_num); + uint32_t period = PWM_MAX_FREQ/frequency; + mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); + mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); + mp_printf(&mp_plat_print, "Timer Freq: %d\n", source_freq/(source_freq / PWM_MAX_FREQ)); + mp_printf(&mp_plat_print, "Actual Freq: %d\n", (source_freq/(source_freq / PWM_MAX_FREQ))/period); + mp_printf(&mp_plat_print, "Period: %d\n", (PWM_MAX_FREQ/frequency)); TIM_HandleTypeDef tim = {0}; - tim.Instance = TIM4; - tim.Init.Period = LED_PWM_TIM_PERIOD - 1; - tim.Init.Prescaler = timer_get_source_freq(pwm_cfg->tim_id) / 1000000 - 1; // TIM runs at 1MHz + tim.Instance = TIM10; + tim.Init.Period = period - 1; + tim.Init.Prescaler = (source_freq / PWM_MAX_FREQ) - 1; // TIM runs at 16MHz tim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; tim.Init.CounterMode = TIM_COUNTERMODE_UP; tim.Init.RepetitionCounter = 0; - HAL_TIM_PWM_Init(&tim); + if(HAL_TIM_PWM_Init(&tim) == HAL_OK) { + mp_printf(&mp_plat_print, "Tim Init Success\n"); + } // PWM configuration TIM_OC_InitTypeDef oc_init; oc_init.OCMode = TIM_OCMODE_PWM1; - oc_init.Pulse = 0; // off - oc_init.OCPolarity = MICROPY_HW_LED_INVERTED ? TIM_OCPOLARITY_LOW : TIM_OCPOLARITY_HIGH; + oc_init.Pulse = (period*duty)/100 - 1; + oc_init.OCPolarity = TIM_OCPOLARITY_LOW; oc_init.OCFastMode = TIM_OCFAST_DISABLE; - oc_init.OCNPolarity = TIM_OCNPOLARITY_HIGH; // needed for TIM1 and TIM8 + oc_init.OCNPolarity = TIM_OCNPOLARITY_LOW; // needed for TIM1 and TIM8 oc_init.OCIdleState = TIM_OCIDLESTATE_SET; // needed for TIM1 and TIM8 oc_init.OCNIdleState = TIM_OCNIDLESTATE_SET; // needed for TIM1 and TIM8 - HAL_TIM_PWM_ConfigChannel(&tim, &oc_init, pwm_cfg->tim_channel); - HAL_TIM_PWM_Start(&tim, pwm_cfg->tim_channel); + if(HAL_TIM_PWM_ConfigChannel(&tim, &oc_init, tim_chan) == HAL_OK) { + mp_printf(&mp_plat_print, "Channel Config Success\n"); + } + if(HAL_TIM_PWM_Start(&tim, tim_chan) == HAL_OK) { + mp_printf(&mp_plat_print, "Start Success\n"); + } + return PWMOUT_OK; } diff --git a/ports/stm32f4/mpconfigport.mk b/ports/stm32f4/mpconfigport.mk index ffe586898e..bce68f99f4 100644 --- a/ports/stm32f4/mpconfigport.mk +++ b/ports/stm32f4/mpconfigport.mk @@ -20,6 +20,7 @@ CIRCUITPY_DIGITALIO = 1 CIRCUITPY_ANALOGIO = 1 CIRCUITPY_MICROCONTROLLER = 1 CIRCUITPY_BUSIO = 1 +CIRCUITPY_PULSEIO = 1 CIRCUITPY_OS = 1 CIRCUITPY_STORAGE = 1 CIRCUITPY_RANDOM = 1 From cf7efee0d37144835e60d3e858df8ede29d9b61a Mon Sep 17 00:00:00 2001 From: Hierophect Date: Thu, 24 Oct 2019 18:00:50 -0400 Subject: [PATCH 10/38] Add f405 pindefs --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 2 +- ports/stm32f4/peripherals/stm32f4/periph.h | 16 ++++ .../peripherals/stm32f4/stm32f405xx/periph.c | 76 ++++++++++++++++++- 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index ba5fc06c1d..4e2075b4d1 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -33,7 +33,7 @@ #include "supervisor/shared/translate.h" #include "stm32f4xx_hal.h" -#define PWM_MAX_FREQ 1000000 +#define PWM_MAX_FREQ 6000000 // Get the frequency (in Hz) of the source clock for the given timer. // On STM32F405/407/415/417 there are 2 cases for how the clock freq is set. diff --git a/ports/stm32f4/peripherals/stm32f4/periph.h b/ports/stm32f4/peripherals/stm32f4/periph.h index 82f179147b..d825b4831b 100644 --- a/ports/stm32f4/peripherals/stm32f4/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/periph.h @@ -99,6 +99,22 @@ typedef struct { .pin = spi_pin, \ } +//Timers +typedef struct { + uint8_t tim_index:4; + uint8_t altfn_index:4; + uint8_t tim_channel:4; + const mcu_pin_obj_t * pin; +} mcu_tim_pin_obj_t; + +#define TIM(index, alt, channel, tim_pin) \ +{ \ + .tim_index = index, \ + .altfn_index = alt, \ + .tim_channel = channel, \ + .pin = tim_pin, \ +} + //Starter Lines #ifdef STM32F411xE diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c index 7b0a54e55e..5b2c211cbd 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c @@ -85,4 +85,78 @@ const mcu_spi_nss_obj_t mcu_spi_nss_list[6] = { SPI(3, 6, &pin_PA04), SPI(3, 6, &pin_PA15), }; -//UART, Etc + +//Timers +//TIM6 and TIM7 are basic timers that are only used by DAC, and don't have pins +TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, TIM9, TIM10, + TIM11, TIM12, TIM13, TIM14}; + +const mcu_tim_pin_obj_t mcu_tim_pin_list[66] = { + TIM(2,1,1,&pin_PA00), + TIM(5,2,1,&pin_PA00), + TIM(2,1,2,&pin_PA01), + TIM(5,2,2,&pin_PA01), + TIM(2,1,3,&pin_PA02), + TIM(5,2,3,&pin_PA02), + TIM(2,1,4,&pin_PA03), + TIM(5,2,4,&pin_PA03), + TIM(9,3,1,&pin_PA02), + TIM(9,3,2,&pin_PA03), + TIM(3,2,1,&pin_PA06), + TIM(13,9,1,&pin_PA06), + TIM(3,2,2,&pin_PA07), + TIM(14,9,1,&pin_PA07), + TIM(1,1,1,&pin_PA08), + TIM(1,1,2,&pin_PA09), + TIM(1,1,3,&pin_PA10), + TIM(1,1,4,&pin_PA11), + TIM(2,1,1,&pin_PA15), + TIM(3,2,3,&pin_PB00), + TIM(3,2,4,&pin_PB01), + TIM(2,1,2,&pin_PB03), + TIM(3,2,1,&pin_PB04), + TIM(3,2,2,&pin_PB05), + TIM(4,2,1,&pin_PB06), + TIM(4,2,2,&pin_PB07), + TIM(4,2,3,&pin_PB08), + TIM(10,2,1,&pin_PB08), + TIM(4,2,4,&pin_PB09), + TIM(11,2,1,&pin_PB09), + TIM(2,1,3,&pin_PB10), + TIM(2,1,4,&pin_PB11), + TIM(12,9,1,&pin_PB14), + TIM(12,9,2,&pin_PB15), + TIM(3,2,1,&pin_PC06), + TIM(3,2,2,&pin_PC07), + TIM(3,2,3,&pin_PC08), + TIM(3,2,4,&pin_PC09), + TIM(8,3,1,&pin_PC06), + TIM(8,3,2,&pin_PC07), + TIM(8,3,3,&pin_PC08), + TIM(8,3,4,&pin_PC09), + TIM(4,2,1,&pin_PD12), + TIM(4,2,2,&pin_PD13), + TIM(4,2,3,&pin_PD14), + TIM(4,2,4,&pin_PD15), + TIM(9,3,1,&pin_PE05), + TIM(9,3,2,&pin_PE06), + TIM(1,1,1,&pin_PE09), + TIM(1,1,2,&pin_PE11), + TIM(1,1,3,&pin_PE13), + TIM(1,1,4,&pin_PE14), + TIM(10,3,1,&pin_PF06), + TIM(11,3,1,&pin_PF07), + TIM(13,9,1,&pin_PF08), + TIM(14,9,1,&pin_PF09), + TIM(12,9,1,&pin_PH06), + TIM(12,9,2,&pin_PH09), + TIM(5,2,1,&pin_PH10), + TIM(5,2,2,&pin_PH11), + TIM(5,2,3,&pin_PH12), + TIM(5,2,4,&pin_PI00), + TIM(8,3,4,&pin_PI02), + TIM(8,3,1,&pin_PI05), + TIM(8,3,2,&pin_PI06), + TIM(8,3,3,&pin_PI07), +}; + From 4b742f88d9d7b56a81de8559f3d55bf38bf03922 Mon Sep 17 00:00:00 2001 From: Thea Flowers Date: Fri, 25 Oct 2019 10:50:27 -0700 Subject: [PATCH 11/38] Fix spelling --- ports/atmel-samd/common-hal/pulseio/PWMOut.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.c b/ports/atmel-samd/common-hal/pulseio/PWMOut.c index 92305161f4..0adb23fc5d 100644 --- a/ports/atmel-samd/common-hal/pulseio/PWMOut.c +++ b/ports/atmel-samd/common-hal/pulseio/PWMOut.c @@ -323,9 +323,9 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { } extern void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty) { - // Store the unadjusted duty cycle. It turns out the the process of adjusting and calucating + // Store the unadjusted duty cycle. It turns out the the process of adjusting and calculating // the duty cycle here and reading it back is lossy - the value will decay over time. - // Track it here so that if frequency is changed we can use this value to recalcuate the + // Track it here so that if frequency is changed we can use this value to recalculate the // proper duty cycle. // See https://github.com/adafruit/circuitpython/issues/2086 for more details self->duty_cycle = duty; From 6782948751d5ca711213564f59b28dc3c4ca85bb Mon Sep 17 00:00:00 2001 From: Thea Flowers Date: Fri, 25 Oct 2019 10:56:41 -0700 Subject: [PATCH 12/38] Note behavior in documentation --- shared-bindings/pulseio/PWMOut.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/shared-bindings/pulseio/PWMOut.c b/shared-bindings/pulseio/PWMOut.c index 40981e0a81..53b88c61a5 100644 --- a/shared-bindings/pulseio/PWMOut.c +++ b/shared-bindings/pulseio/PWMOut.c @@ -162,6 +162,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pwmout___exit___obj, 4, 4, pu //| 16 bit value that dictates how much of one cycle is high (1) versus low //| (0). 0xffff will always be high, 0 will always be low and 0x7fff will //| be half high and then half low. +//| +//| Depending on how PWM is implemented on a specific board, the internal +//| representation for duty cycle might have less than 16 bits of resolution. +//| Reading this property will return the value from the internal representation, +//| so it may differ from the value set. STATIC mp_obj_t pulseio_pwmout_obj_get_duty_cycle(mp_obj_t self_in) { pulseio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -193,6 +198,12 @@ const mp_obj_property_t pulseio_pwmout_duty_cycle_obj = { //| 32 bit value that dictates the PWM frequency in Hertz (cycles per //| second). Only writeable when constructed with ``variable_frequency=True``. //| +//| Depending on how PWM is implemented on a specific board, the internal value +//| for the PWM's duty cycle may need to be recalculated when the frequency +//| changes. In these cases, the duty cycle is automatically recalculated +//| from the original duty cycle value. This should happen without any need +//| to manually re-set the duty cycle. +//| STATIC mp_obj_t pulseio_pwmout_obj_get_frequency(mp_obj_t self_in) { pulseio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); From cb491e855c0730466f00dae65727909e4ada40f1 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Sun, 27 Oct 2019 14:31:25 -0400 Subject: [PATCH 13/38] WIP --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 272 +++++++++++++++--- ports/stm32f4/common-hal/pulseio/PWMOut.h | 4 +- ports/stm32f4/peripherals/stm32f4/periph.h | 4 +- .../peripherals/stm32f4/stm32f405xx/periph.h | 6 + 4 files changed, 243 insertions(+), 43 deletions(-) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index 4e2075b4d1..c74eb670fe 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -5,7 +5,7 @@ * * Copyright (c) 2018 Dan Halbert for Adafruit Industries * Copyright (c) 2019 Lucian Copeland for Adafruit Industries - * Utilizes code from Micropython, Copyright (c) 2013-2016 Damien P. George + * Uses code from Micropython, Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,12 +34,15 @@ #include "stm32f4xx_hal.h" #define PWM_MAX_FREQ 6000000 +#define ALL_CLOCKS 0xFFFF -// Get the frequency (in Hz) of the source clock for the given timer. -// On STM32F405/407/415/417 there are 2 cases for how the clock freq is set. -// If the APB prescaler is 1, then the timer clock is equal to its respective -// APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its -// respective APB clock. See DM00031020 Rev 4, page 115. +STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN]; +STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN]; + +STATIC void tim_clock_enable(uint16_t mask); +STATIC void tim_clock_disable(uint16_t mask); + +// Get the frequency (in Hz) static uint32_t timer_get_source_freq(uint32_t tim_id) { uint32_t source, clk_div; if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) { @@ -59,6 +62,7 @@ static uint32_t timer_get_source_freq(uint32_t tim_id) { } void pwmout_reset(void) { + tim_clock_disable(ALL_CLOCKS); } void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self) { @@ -72,22 +76,96 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, uint16_t duty, uint32_t frequency, bool variable_frequency) { - //Using PB08: Tim4 Ch3 for testing - int tim_num = 10; - int tim_chan = TIM_CHANNEL_1; + if (frequency == 0 || frequency > 6000000) { + return PWMOUT_INVALID_FREQUENCY; + } + + TIM_TypeDef * TIMx; + //TODO: style/safety question, use this instead? + //uint8_t tim_num_pins = TIM_PIN_ARRAY_LEN; + uint8_t tim_num = sizeof(mcu_tim_pin_list)/sizeof(*mcu_tim_pin_list); + //TODO: use an enum to make this prettier? + bool tim_chan_taken = false; + bool tim_taken_f_mismatch = false; + bool var_freq_mismatch = false; + bool first_time_setup = true; + + for(uint i = 0; i < tim_num; i++) { + //if pin is same + if(mcu_tim_pin_list[i].pin = pin) { + //check if the timer has a channel active + if (reserved_tim[mcu_tim_pin_list[i].tim_index] != 0) { + //is it the same channel? (or all channels reserved by a var-freq) + if(reserved_tim[mcu_tim_pin_list[i].tim_index-1] & 1<<(mcu_tim_pin_list[i].channel_index-1)) { + tim_chan_taken = true; + continue; //keep looking, might be another viable option + } + //If the frequencies are the same it's ok + if(tim_frequencies[mcu_tim_pin_list[i].tim_index-1] != frequency) { + tim_taken_f_mismatch = true; + continue; //keep looking + } + //you can't put a variable frequency on a partially reserved timer + if(variable_frequency) { + var_freq_mismatch = true; + continue; //keep looking + } + first_time_setup = false; //skip setting up the timer + } + //No problems taken, so set it up + self->tim = &mcu_tim_pin_list[i]; + break; + } + } + + //handle valid/invalid timer instance + //TODO: why doesn't PWM handle its own value errors like every other module? + //The samd value errors don't really fit for STM32. + if(self->tim!=NULL) { + //create instance + TIMx = mcu_tim_banks[self->tim->tim_index-1]; + //reserve timer/channel + if (variable_frequency) { + reserved_tim[self->tim->tim_index-1] = 0x0F; + } else { + reserved_tim[self->tim->tim_index-1] |= 1<tim->channel_index-1; + } + } else { //no match found + if (tim_chan_taken) { + mp_raise_ValueError(translate("Timer hardware is reserved")); + //return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; + } else if (tim_taken_f_mismatch) { + mp_raise_ValueError(translate("Frequency mismatch with existing reserved channel")); + //return PWMOUT_INVALID_FREQUENCY; + } else if (var_freq_mismatch) { + mp_raise_ValueError(translate("Cannot vary frequency of a partially reserved timer")); + //return PWMOUT_INVALID_FREQUENCY; //I guess? + } else { + mp_raise_ValueError(translate("Invalid pins")); + //return PWMOUT_INVALID_PIN; + } + } GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = pin_mask(pin->number); - GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; - GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = 3;//2; //2 is timer 4 + GPIO_InitStruct.Alternate = self->tim->altfn_index; HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct); - //__HAL_RCC_TIM4_CLK_ENABLE(); - __HAL_RCC_TIM10_CLK_ENABLE(); + //TODO: factor all of these into periph.c? + tim_clock_enable(1<<(self->tim->tim_index - 1)); - uint32_t source_freq = timer_get_source_freq(tim_num); + //translate channel into handle value + switch (self->tim->channel_index) { + case 1: self->channel = TIM_CHANNEL_1; break; + case 2: self->channel = TIM_CHANNEL_2; break; + case 3: self->channel = TIM_CHANNEL_3; break; + case 4: self->channel = TIM_CHANNEL_4; break; + } + + uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); uint32_t period = PWM_MAX_FREQ/frequency; mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); @@ -95,48 +173,82 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, mp_printf(&mp_plat_print, "Actual Freq: %d\n", (source_freq/(source_freq / PWM_MAX_FREQ))/period); mp_printf(&mp_plat_print, "Period: %d\n", (PWM_MAX_FREQ/frequency)); - TIM_HandleTypeDef tim = {0}; - tim.Instance = TIM10; - tim.Init.Period = period - 1; - tim.Init.Prescaler = (source_freq / PWM_MAX_FREQ) - 1; // TIM runs at 16MHz - tim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; - tim.Init.CounterMode = TIM_COUNTERMODE_UP; - tim.Init.RepetitionCounter = 0; - if(HAL_TIM_PWM_Init(&tim) == HAL_OK) { - mp_printf(&mp_plat_print, "Tim Init Success\n"); + //Timer init + self->handle.Instance = TIMx; + self->handle.Init.Period = period - 1; + self->handle.Init.Prescaler = (source_freq / PWM_MAX_FREQ) - 1; // TIM runs at ~6MHz + self->handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + self->handle.Init.CounterMode = TIM_COUNTERMODE_UP; + self->handle.Init.RepetitionCounter = 0; + + //only run init if this is the first instance of this timer + if(first_time_setup) { + if(HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { + mp_raise_ValueError(translate("Timer Init Error")); + } } - // PWM configuration - TIM_OC_InitTypeDef oc_init; - oc_init.OCMode = TIM_OCMODE_PWM1; - oc_init.Pulse = (period*duty)/100 - 1; - oc_init.OCPolarity = TIM_OCPOLARITY_LOW; - oc_init.OCFastMode = TIM_OCFAST_DISABLE; - oc_init.OCNPolarity = TIM_OCNPOLARITY_LOW; // needed for TIM1 and TIM8 - oc_init.OCIdleState = TIM_OCIDLESTATE_SET; // needed for TIM1 and TIM8 - oc_init.OCNIdleState = TIM_OCNIDLESTATE_SET; // needed for TIM1 and TIM8 - if(HAL_TIM_PWM_ConfigChannel(&tim, &oc_init, tim_chan) == HAL_OK) { - mp_printf(&mp_plat_print, "Channel Config Success\n"); + //Channel/PWM init + self->chan_handle.OCMode = TIM_OCMODE_PWM1; + self->chan_handle.Pulse = (period*duty)/100 - 1; + self->chan_handle.OCPolarity = TIM_OCPOLARITY_LOW; + self->chan_handle.OCFastMode = TIM_OCFAST_DISABLE; + self->chan_handle.OCNPolarity = TIM_OCNPOLARITY_LOW; // needed for TIM1 and TIM8 + self->chan_handle.OCIdleState = TIM_OCIDLESTATE_SET; // needed for TIM1 and TIM8 + self->chan_handle.OCNIdleState = TIM_OCNIDLESTATE_SET; // needed for TIM1 and TIM8 + if(HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Channel Init Error")); } - if(HAL_TIM_PWM_Start(&tim, tim_chan) == HAL_OK) { - mp_printf(&mp_plat_print, "Start Success\n"); + if(HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Error starting PWM")); } + self->variable_frequency = variable_frequency; + self->frequency = frequency; + self->duty_cycle = duty; + return PWMOUT_OK; } bool common_hal_pulseio_pwmout_deinited(pulseio_pwmout_obj_t* self) { - return true; + return self->tim == mp_const_none; } void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { + if (common_hal_pulseio_pwmout_deinited(self)) { + return; + } + //var freq shuts down entire timer, others just their channel + if(self->variable_frequency) { + reserved_tim[self->tim->tim_index-1] = 0x00; + } else { + reserved_tim[self->tim->tim_index-1] &= !(1<tim->channel_index); + HAL_TIM_PWM_Stop(&self->handle, self->channel); + } + reset_pin_number(self->tim->pin->port,self->tim->pin->number); + self->tim = mp_const_none; + + //if reserved timer has no active channels, we can disable it + if (!reserved_tim[self->tim->tim_index-1]) { + tim_frequencies[self->tim->tim_index-1] = 0x00; + tim_clock_disable(1<<(self->tim->tim_index-1)); + } } void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) { + HAL_TIM_PWM_Stop(&self->handle, self->channel); + + self->chan_handle.Pulse = ((PWM_MAX_FREQ/self->frequency)*duty_cycle)/100 - 1; + if(HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Channel Re-Init Error")); + } + if(HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Error restarting PWM")); + } } uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { - return 0; + return self->duty_cycle; } void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency) { @@ -147,5 +259,85 @@ uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) { } bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) { - return 0; + return self->variable_frequency; } + +STATIC void tim_clock_enable(uint16_t mask) { + #ifdef TIM1 + if(mask & 1<<0) __HAL_RCC_TIM1_CLK_ENABLE(); + #endif + #ifdef TIM2 + if(mask & 1<<1) __HAL_RCC_TIM2_CLK_ENABLE(); + #endif + #ifdef TIM3 + if(mask & 1<<2) __HAL_RCC_TIM3_CLK_ENABLE(); + #endif + #ifdef TIM4 + if(mask & 1<<3) __HAL_RCC_TIM4_CLK_ENABLE(); + #endif + #ifdef TIM5 + if(mask & 1<<4) __HAL_RCC_TIM5_CLK_ENABLE(); + #endif + //6 and 7 are reserved ADC timers + #ifdef TIM8 + if(mask & 1<<7) __HAL_RCC_TIM8_CLK_ENABLE(); + #endif + #ifdef TIM9 + if(mask & 1<<8) __HAL_RCC_TIM9_CLK_ENABLE(); + #endif + #ifdef TIM10 + if(mask & 1<<9) __HAL_RCC_TIM10_CLK_ENABLE(); + #endif + #ifdef TIM11 + if(mask & 1<<10) __HAL_RCC_TIM11_CLK_ENABLE(); + #endif + #ifdef TIM12 + if(mask & 1<<11) __HAL_RCC_TIM12_CLK_ENABLE(); + #endif + #ifdef TIM13 + if(mask & 1<<12) __HAL_RCC_TIM13_CLK_ENABLE(); + #endif + #ifdef TIM14 + if(mask & 1<<13) __HAL_RCC_TIM14_CLK_ENABLE(); + #endif +} + +STATIC void tim_clock_disable(uint16_t mask) { + #ifdef TIM1 + if(mask & 1<<0) __HAL_RCC_TIM1_CLK_DISABLE(); + #endif + #ifdef TIM2 + if(mask & 1<<1) __HAL_RCC_TIM2_CLK_DISABLE(); + #endif + #ifdef TIM3 + if(mask & 1<<2) __HAL_RCC_TIM3_CLK_DISABLE(); + #endif + #ifdef TIM4 + if(mask & 1<<3) __HAL_RCC_TIM4_CLK_DISABLE(); + #endif + #ifdef TIM5 + if(mask & 1<<4) __HAL_RCC_TIM5_CLK_DISABLE(); + #endif + //6 and 7 are reserved ADC timers + #ifdef TIM8 + if(mask & 1<<7) __HAL_RCC_TIM8_CLK_DISABLE(); + #endif + #ifdef TIM9 + if(mask & 1<<8) __HAL_RCC_TIM9_CLK_DISABLE(); + #endif + #ifdef TIM10 + if(mask & 1<<9) __HAL_RCC_TIM10_CLK_DISABLE(); + #endif + #ifdef TIM11 + if(mask & 1<<10) __HAL_RCC_TIM11_CLK_DISABLE(); + #endif + #ifdef TIM12 + if(mask & 1<<11) __HAL_RCC_TIM12_CLK_DISABLE(); + #endif + #ifdef TIM13 + if(mask & 1<<12) __HAL_RCC_TIM13_CLK_DISABLE(); + #endif + #ifdef TIM14 + if(mask & 1<<13) __HAL_RCC_TIM14_CLK_DISABLE(); + #endif +} \ No newline at end of file diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.h b/ports/stm32f4/common-hal/pulseio/PWMOut.h index 58adb196c8..97777d3ca6 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.h +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.h @@ -31,7 +31,9 @@ typedef struct { mp_obj_base_t base; - uint8_t pin_number; + TIM_HandleTypeDef handle; + TIM_OC_InitTypeDef chan_handle; + const mcu_tim_pin_obj_t *tim; uint8_t channel: 7; bool variable_frequency: 1; uint16_t duty_cycle; diff --git a/ports/stm32f4/peripherals/stm32f4/periph.h b/ports/stm32f4/peripherals/stm32f4/periph.h index d825b4831b..d066b2be77 100644 --- a/ports/stm32f4/peripherals/stm32f4/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/periph.h @@ -103,7 +103,7 @@ typedef struct { typedef struct { uint8_t tim_index:4; uint8_t altfn_index:4; - uint8_t tim_channel:4; + uint8_t channel_index:4; const mcu_pin_obj_t * pin; } mcu_tim_pin_obj_t; @@ -111,7 +111,7 @@ typedef struct { { \ .tim_index = index, \ .altfn_index = alt, \ - .tim_channel = channel, \ + .channel_index = channel, \ .pin = tim_pin, \ } diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h index cb9b33f6eb..6ceb9c9908 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h @@ -41,5 +41,11 @@ extern const mcu_spi_mosi_obj_t mcu_spi_mosi_list[6]; extern const mcu_spi_miso_obj_t mcu_spi_miso_list[6]; extern const mcu_spi_nss_obj_t mcu_spi_nss_list[6]; +#define TIM_BANK_ARRAY_LEN 14 +TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, TIM9, TIM10, + TIM11, TIM12, TIM13, TIM14}; +#define TIM_PIN_ARRAY_LEN 66 +const mcu_tim_pin_obj_t mcu_tim_pin_list[66] = { + #endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F405XX_PERIPH_H \ No newline at end of file From 978cec0316b17809e68862beecdf9456a25cc439 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 27 Oct 2019 16:41:56 -0500 Subject: [PATCH 14/38] pixelbuf: correct trivial typos --- shared-bindings/_bleio/Service.c | 2 +- shared-bindings/_pixelbuf/__init__.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c index da5633f2a3..c9b8288070 100644 --- a/shared-bindings/_bleio/Service.c +++ b/shared-bindings/_bleio/Service.c @@ -49,7 +49,7 @@ //| //| .. classmethod:: add_to_peripheral(peripheral, uuid, *, secondary=False) //| -//| Create a new Service object, identitied by the specified UUID, and add it +//| Create a new Service object, identified by the specified UUID, and add it //| to the given Peripheral. //| //| To mark the service as secondary, pass `True` as :py:data:`secondary`. diff --git a/shared-bindings/_pixelbuf/__init__.c b/shared-bindings/_pixelbuf/__init__.c index 48b9f1cef1..eb0cb29842 100644 --- a/shared-bindings/_pixelbuf/__init__.c +++ b/shared-bindings/_pixelbuf/__init__.c @@ -55,7 +55,7 @@ //| .. class:: ByteOrder() //| -//| Classes representing byteorders for circuitpython +//| Classes representing byteorders for CircuitPython //| .. attribute:: bpp @@ -284,7 +284,7 @@ PIXELBUF_BYTEORDER(LBRG, 4, 3, 1, 2, 0, false, true) //| * **bpp** 4 //| * **has_luminosity** True //| -//| Actual format commonly used by DotStar (5 bit luninance value) +//| Actual format commonly used by DotStar (5 bit luminance value) PIXELBUF_BYTEORDER(LBGR, 4, 3, 2, 1, 0, false, true) STATIC const mp_rom_map_elem_t pixelbuf_module_globals_table[] = { From 0657884fca377bd055cec3851bf4fbcaf5005095 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 27 Oct 2019 16:42:04 -0500 Subject: [PATCH 15/38] audiobus: correct trivial typo --- shared-bindings/audiobusio/I2SOut.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c index 2cd2b67289..81383c7776 100644 --- a/shared-bindings/audiobusio/I2SOut.c +++ b/shared-bindings/audiobusio/I2SOut.c @@ -62,7 +62,7 @@ //| import time //| import math //| -//| # Generate one period of sine wav. +//| # Generate one period of sine wave. //| length = 8000 // 440 //| sine_wave = array.array("H", [0] * length) //| for i in range(length): From c208586bf11a3902157a113983a8461afedfa023 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 27 Oct 2019 16:42:18 -0500 Subject: [PATCH 16/38] audioio: correct trivial typo --- shared-bindings/audioio/__init__.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/audioio/__init__.c b/shared-bindings/audioio/__init__.c index 7fa37d5c51..02a5fe1eee 100644 --- a/shared-bindings/audioio/__init__.c +++ b/shared-bindings/audioio/__init__.c @@ -68,7 +68,7 @@ //| //| For compatibility with CircuitPython 4.x, some builds allow the items in //| `audiocore` to be imported from `audioio`. This will be removed for all -//| boards in a future build of CicuitPython. +//| boards in a future build of CircuitPython. //| STATIC const mp_rom_map_elem_t audioio_module_globals_table[] = { From 0cd8c3d5a8b983f6efcf3aa80b99a18c95734f28 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Sun, 27 Oct 2019 19:17:01 -0400 Subject: [PATCH 17/38] Add all basic functions, never reset, dynamic pulse changes --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 100 ++++++++++++++---- ports/stm32f4/common-hal/pulseio/PWMOut.h | 5 + .../peripherals/stm32f4/stm32f405xx/periph.c | 20 ++-- .../peripherals/stm32f4/stm32f405xx/periph.h | 5 +- ports/stm32f4/supervisor/port.c | 2 + 5 files changed, 99 insertions(+), 33 deletions(-) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index c74eb670fe..48f8320fb9 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -31,13 +31,17 @@ #include "common-hal/pulseio/PWMOut.h" #include "shared-bindings/pulseio/PWMOut.h" #include "supervisor/shared/translate.h" + +#include "shared-bindings/microcontroller/__init__.h" #include "stm32f4xx_hal.h" +#include "common-hal/microcontroller/Pin.h" #define PWM_MAX_FREQ 6000000 #define ALL_CLOCKS 0xFFFF STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN]; STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN]; +STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN]; STATIC void tim_clock_enable(uint16_t mask); STATIC void tim_clock_disable(uint16_t mask); @@ -62,13 +66,37 @@ static uint32_t timer_get_source_freq(uint32_t tim_id) { } void pwmout_reset(void) { - tim_clock_disable(ALL_CLOCKS); + uint16_t never_reset_mask = 0x00; + for(int i=0;ihandle.Instance) { + never_reset_tim[i] = true; + never_reset_pin_number(self->tim->pin->port, self->tim->pin->number); + break; + } + } } void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self) { + //TODO: doesn't this need an equivalent release pin in microcontroller.c? + //I don't see that implemented in any port. + for(size_t i = 0 ; i < TIM_BANK_ARRAY_LEN; i++) { + if (mcu_tim_banks[i] == self->handle.Instance) { + never_reset_tim[i] = false; + break; + } + } } pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, @@ -77,7 +105,8 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, uint32_t frequency, bool variable_frequency) { if (frequency == 0 || frequency > 6000000) { - return PWMOUT_INVALID_FREQUENCY; + mp_raise_ValueError(translate("Invalid frequency supplied")); + //return PWMOUT_INVALID_FREQUENCY; } TIM_TypeDef * TIMx; @@ -92,9 +121,9 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, for(uint i = 0; i < tim_num; i++) { //if pin is same - if(mcu_tim_pin_list[i].pin = pin) { + if(mcu_tim_pin_list[i].pin == pin) { //check if the timer has a channel active - if (reserved_tim[mcu_tim_pin_list[i].tim_index] != 0) { + if (reserved_tim[mcu_tim_pin_list[i].tim_index-1] != 0) { //is it the same channel? (or all channels reserved by a var-freq) if(reserved_tim[mcu_tim_pin_list[i].tim_index-1] & 1<<(mcu_tim_pin_list[i].channel_index-1)) { tim_chan_taken = true; @@ -128,8 +157,9 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, if (variable_frequency) { reserved_tim[self->tim->tim_index-1] = 0x0F; } else { - reserved_tim[self->tim->tim_index-1] |= 1<tim->channel_index-1; + reserved_tim[self->tim->tim_index-1] |= 1<<(self->tim->channel_index-1); } + tim_frequencies[self->tim->tim_index-1] = frequency; } else { //no match found if (tim_chan_taken) { mp_raise_ValueError(translate("Timer hardware is reserved")); @@ -167,11 +197,13 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); uint32_t period = PWM_MAX_FREQ/frequency; - mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); - mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); - mp_printf(&mp_plat_print, "Timer Freq: %d\n", source_freq/(source_freq / PWM_MAX_FREQ)); - mp_printf(&mp_plat_print, "Actual Freq: %d\n", (source_freq/(source_freq / PWM_MAX_FREQ))/period); - mp_printf(&mp_plat_print, "Period: %d\n", (PWM_MAX_FREQ/frequency)); + //TODO: remove before merging. + // mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); + // mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); + // mp_printf(&mp_plat_print, "Timer Freq: %d\n", source_freq/(source_freq / PWM_MAX_FREQ)); + // mp_printf(&mp_plat_print, "Actual Freq: %d\n", (source_freq/(source_freq / PWM_MAX_FREQ))/period); + // mp_printf(&mp_plat_print, "Duty: %d\n", duty); + // mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index); //Timer init self->handle.Instance = TIMx; @@ -222,7 +254,7 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { if(self->variable_frequency) { reserved_tim[self->tim->tim_index-1] = 0x00; } else { - reserved_tim[self->tim->tim_index-1] &= !(1<tim->channel_index); + reserved_tim[self->tim->tim_index-1] &= ~(1<tim->channel_index); HAL_TIM_PWM_Stop(&self->handle, self->channel); } reset_pin_number(self->tim->pin->port,self->tim->pin->number); @@ -236,15 +268,14 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { } void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) { - HAL_TIM_PWM_Stop(&self->handle, self->channel); + uint16_t duty = duty_cycle/655; + uint32_t period = PWM_MAX_FREQ/self->frequency; + uint32_t input = (period*duty)/100; + //TODO: remove before merging + //mp_printf(&mp_plat_print, "duty_cycle %d, Duty: %d, Input %d\n", duty_cycle, duty, input); + __HAL_TIM_SET_COMPARE(&self->handle, self->channel, input); - self->chan_handle.Pulse = ((PWM_MAX_FREQ/self->frequency)*duty_cycle)/100 - 1; - if(HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { - mp_raise_ValueError(translate("Channel Re-Init Error")); - } - if(HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { - mp_raise_ValueError(translate("Error restarting PWM")); - } + self->duty_cycle = duty; } uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { @@ -252,10 +283,39 @@ uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { } void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency) { + if (frequency == 0 || frequency > 6000000) { + mp_raise_ValueError(translate("Invalid PWM frequency")); + } + if (frequency == self->frequency) return; + + uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); + uint32_t period = PWM_MAX_FREQ/frequency; + + //shut down + HAL_TIM_PWM_Stop(&self->handle, self->channel); + tim_clock_disable(1<<(self->tim->tim_index-1)); + + //Only change altered values + self->handle.Init.Period = period - 1; + self->handle.Init.Prescaler = (source_freq / PWM_MAX_FREQ) - 1; // TIM runs at ~6MHz + + //restart everything + if(HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { + mp_raise_ValueError(translate("Timer Re-Init Error")); + } + if(HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Channel Re-Init Error")); + } + if(HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Error restarting PWM")); + } + + tim_frequencies[self->tim->tim_index-1] = frequency; + self->frequency = frequency; } uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) { - return 0; + return self->frequency; } bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) { diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.h b/ports/stm32f4/common-hal/pulseio/PWMOut.h index 97777d3ca6..a7784204ce 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.h +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.h @@ -27,6 +27,11 @@ #ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H #define MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H +#include "common-hal/microcontroller/Pin.h" + +#include "stm32f4xx_hal.h" +#include "stm32f4/periph.h" + #include "py/obj.h" typedef struct { diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c index 5b2c211cbd..35dc7eb7eb 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c @@ -148,15 +148,15 @@ const mcu_tim_pin_obj_t mcu_tim_pin_list[66] = { TIM(11,3,1,&pin_PF07), TIM(13,9,1,&pin_PF08), TIM(14,9,1,&pin_PF09), - TIM(12,9,1,&pin_PH06), - TIM(12,9,2,&pin_PH09), - TIM(5,2,1,&pin_PH10), - TIM(5,2,2,&pin_PH11), - TIM(5,2,3,&pin_PH12), - TIM(5,2,4,&pin_PI00), - TIM(8,3,4,&pin_PI02), - TIM(8,3,1,&pin_PI05), - TIM(8,3,2,&pin_PI06), - TIM(8,3,3,&pin_PI07), + // TIM(12,9,1,&pin_PH06), + // TIM(12,9,2,&pin_PH09), + // TIM(5,2,1,&pin_PH10), + // TIM(5,2,2,&pin_PH11), + // TIM(5,2,3,&pin_PH12), + // TIM(5,2,4,&pin_PI00), + // TIM(8,3,4,&pin_PI02), + // TIM(8,3,1,&pin_PI05), + // TIM(8,3,2,&pin_PI06), + // TIM(8,3,3,&pin_PI07), }; diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h index 6ceb9c9908..0b75965d97 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h @@ -42,10 +42,9 @@ extern const mcu_spi_miso_obj_t mcu_spi_miso_list[6]; extern const mcu_spi_nss_obj_t mcu_spi_nss_list[6]; #define TIM_BANK_ARRAY_LEN 14 -TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, TIM9, TIM10, - TIM11, TIM12, TIM13, TIM14}; +TIM_TypeDef * mcu_tim_banks[14]; #define TIM_PIN_ARRAY_LEN 66 -const mcu_tim_pin_obj_t mcu_tim_pin_list[66] = { +const mcu_tim_pin_obj_t mcu_tim_pin_list[66]; #endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F405XX_PERIPH_H \ No newline at end of file diff --git a/ports/stm32f4/supervisor/port.c b/ports/stm32f4/supervisor/port.c index 502202f522..602bec4be8 100644 --- a/ports/stm32f4/supervisor/port.c +++ b/ports/stm32f4/supervisor/port.c @@ -33,6 +33,7 @@ #include "common-hal/microcontroller/Pin.h" #include "common-hal/busio/I2C.h" #include "common-hal/busio/SPI.h" +#include "common-hal/pulseio/PWMOut.h" #include "stm32f4/clocks.h" #include "stm32f4/gpio.h" @@ -57,6 +58,7 @@ void reset_port(void) { reset_all_pins(); i2c_reset(); spi_reset(); + pwmout_reset(); } void reset_to_bootloader(void) { From 7fd5e9b86741fc37fc8757f65e5dcec8b7562456 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Sun, 27 Oct 2019 19:41:01 -0400 Subject: [PATCH 18/38] Fix issue with changing frequency --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index 48f8320fb9..86f7f67e87 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -293,16 +293,16 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_ //shut down HAL_TIM_PWM_Stop(&self->handle, self->channel); - tim_clock_disable(1<<(self->tim->tim_index-1)); //Only change altered values self->handle.Init.Period = period - 1; self->handle.Init.Prescaler = (source_freq / PWM_MAX_FREQ) - 1; // TIM runs at ~6MHz - //restart everything + //restart everything, adjusting for new speed if(HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { mp_raise_ValueError(translate("Timer Re-Init Error")); } + self->chan_handle.Pulse = (period*self->duty_cycle)/100 - 1; if(HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { mp_raise_ValueError(translate("Channel Re-Init Error")); } From c0f1ce590e600a70ee32f508fbc8d88998cd04fc Mon Sep 17 00:00:00 2001 From: Hierophect Date: Sun, 27 Oct 2019 20:17:10 -0400 Subject: [PATCH 19/38] Add support across dev boards --- .../boards/pyboard_v11/stm32f4xx_hal_conf.h | 2 +- .../stm32f4xx_hal_conf.h | 2 +- .../stm32f4xx_hal_conf.h | 2 +- .../peripherals/stm32f4/stm32f405xx/periph.c | 2 +- .../peripherals/stm32f4/stm32f405xx/periph.h | 4 +- .../peripherals/stm32f4/stm32f411xe/periph.c | 52 ++++++++++++++ .../peripherals/stm32f4/stm32f411xe/periph.h | 5 ++ .../peripherals/stm32f4/stm32f412zx/periph.c | 68 +++++++++++++++++++ .../peripherals/stm32f4/stm32f412zx/periph.h | 5 ++ 9 files changed, 136 insertions(+), 6 deletions(-) diff --git a/ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h index a13e5ecfa3..7a1a9428f8 100644 --- a/ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h +++ b/ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h @@ -61,7 +61,7 @@ /* #define HAL_SD_MODULE_ENABLED */ /* #define HAL_MMC_MODULE_ENABLED */ #define HAL_SPI_MODULE_ENABLED -/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED /* #define HAL_USART_MODULE_ENABLED */ /* #define HAL_IRDA_MODULE_ENABLED */ diff --git a/ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h index b244a69b5e..18d9d60ebe 100644 --- a/ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h +++ b/ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h @@ -61,7 +61,7 @@ /* #define HAL_SD_MODULE_ENABLED */ /* #define HAL_MMC_MODULE_ENABLED */ #define HAL_SPI_MODULE_ENABLED -/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED /* #define HAL_USART_MODULE_ENABLED */ /* #define HAL_IRDA_MODULE_ENABLED */ diff --git a/ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h index 2ad0fee20b..b89240f982 100644 --- a/ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h +++ b/ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h @@ -61,7 +61,7 @@ #define HAL_SD_MODULE_ENABLED /* #define HAL_MMC_MODULE_ENABLED */ #define HAL_SPI_MODULE_ENABLED -/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED /* #define HAL_USART_MODULE_ENABLED */ /* #define HAL_IRDA_MODULE_ENABLED */ diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c index 35dc7eb7eb..859a3d0c23 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c @@ -91,7 +91,7 @@ const mcu_spi_nss_obj_t mcu_spi_nss_list[6] = { TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, TIM9, TIM10, TIM11, TIM12, TIM13, TIM14}; -const mcu_tim_pin_obj_t mcu_tim_pin_list[66] = { +const mcu_tim_pin_obj_t mcu_tim_pin_list[56] = { TIM(2,1,1,&pin_PA00), TIM(5,2,1,&pin_PA00), TIM(2,1,2,&pin_PA01), diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h index 0b75965d97..43e6644507 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h @@ -43,8 +43,8 @@ extern const mcu_spi_nss_obj_t mcu_spi_nss_list[6]; #define TIM_BANK_ARRAY_LEN 14 TIM_TypeDef * mcu_tim_banks[14]; -#define TIM_PIN_ARRAY_LEN 66 -const mcu_tim_pin_obj_t mcu_tim_pin_list[66]; +#define TIM_PIN_ARRAY_LEN 56 +const mcu_tim_pin_obj_t mcu_tim_pin_list[56]; #endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F405XX_PERIPH_H \ No newline at end of file diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c index f0966f785f..1d4034bbf1 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c +++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c @@ -120,3 +120,55 @@ const mcu_spi_nss_obj_t mcu_spi_nss_list[12] = { }; //UART, Etc + +//Timers +//TIM6 and TIM7 are basic timers that are only used by DAC, and don't have pins +TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, NULL, TIM9, TIM10, + TIM11, NULL, NULL, NULL}; + +const mcu_tim_pin_obj_t mcu_tim_pin_list[44] = { + TIM(2,1,1,&pin_PA00), + TIM(5,2,1,&pin_PA00), + TIM(2,1,2,&pin_PA01), + TIM(5,2,2,&pin_PA01), + TIM(2,1,3,&pin_PA02), + TIM(5,2,3,&pin_PA02), + TIM(2,1,4,&pin_PA03), + TIM(5,2,4,&pin_PA03), + TIM(9,3,1,&pin_PA02), + TIM(9,3,2,&pin_PA03), + TIM(3,2,1,&pin_PA06), + TIM(3,2,2,&pin_PA07), + TIM(1,1,1,&pin_PA08), + TIM(1,1,2,&pin_PA09), + TIM(1,1,3,&pin_PA10), + TIM(1,1,4,&pin_PA11), + TIM(2,1,1,&pin_PA15), + TIM(3,2,3,&pin_PB00), + TIM(3,2,4,&pin_PB01), + TIM(2,1,2,&pin_PB03), + TIM(3,2,1,&pin_PB04), + TIM(3,2,2,&pin_PB05), + TIM(4,2,1,&pin_PB06), + TIM(4,2,2,&pin_PB07), + TIM(4,2,3,&pin_PB08), + TIM(10,2,1,&pin_PB08), + TIM(4,2,4,&pin_PB09), + TIM(11,2,1,&pin_PB09), + TIM(2,1,3,&pin_PB10), + TIM(3,2,1,&pin_PC06), + TIM(3,2,2,&pin_PC07), + TIM(3,2,3,&pin_PC08), + TIM(3,2,4,&pin_PC09), + TIM(4,2,1,&pin_PD12), + TIM(4,2,2,&pin_PD13), + TIM(4,2,3,&pin_PD14), + TIM(4,2,4,&pin_PD15), + TIM(9,3,1,&pin_PE05), + TIM(9,3,2,&pin_PE06), + TIM(1,1,1,&pin_PE09), + TIM(1,1,2,&pin_PE11), + TIM(1,1,3,&pin_PE13), + TIM(1,1,4,&pin_PE14), +}; + diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h index 08efa14ca5..3045397a35 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h @@ -41,4 +41,9 @@ extern const mcu_spi_mosi_obj_t mcu_spi_mosi_list[14]; extern const mcu_spi_miso_obj_t mcu_spi_miso_list[12]; extern const mcu_spi_nss_obj_t mcu_spi_nss_list[12]; +#define TIM_BANK_ARRAY_LEN 14 +TIM_TypeDef * mcu_tim_banks[14]; +#define TIM_PIN_ARRAY_LEN 44 +const mcu_tim_pin_obj_t mcu_tim_pin_list[44]; + #endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411VE_PERIPH_H \ No newline at end of file diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c index ea94719ecc..edce2845b8 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c +++ b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c @@ -121,3 +121,71 @@ const mcu_spi_nss_obj_t mcu_spi_nss_list[12] = { }; //UART, Etc + +//Timers +//TIM6 and TIM7 are basic timers that are only used by DAC, and don't have pins +TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, TIM9, TIM10, + TIM11, TIM12, TIM13, TIM14}; + +const mcu_tim_pin_obj_t mcu_tim_pin_list[60] = { + TIM(2,1,1,&pin_PA00), + TIM(5,2,1,&pin_PA00), + TIM(2,1,2,&pin_PA01), + TIM(5,2,2,&pin_PA01), + TIM(2,1,3,&pin_PA02), + TIM(5,2,3,&pin_PA02), + TIM(2,1,4,&pin_PA03), + TIM(5,2,4,&pin_PA03), + TIM(9,3,1,&pin_PA02), + TIM(9,3,2,&pin_PA03), + TIM(3,2,1,&pin_PA06), + TIM(13,9,1,&pin_PA06), + TIM(3,2,2,&pin_PA07), + TIM(14,9,1,&pin_PA07), + TIM(1,1,1,&pin_PA08), + TIM(1,1,2,&pin_PA09), + TIM(1,1,3,&pin_PA10), + TIM(1,1,4,&pin_PA11), + TIM(2,1,1,&pin_PA15), + TIM(3,2,3,&pin_PB00), + TIM(3,2,4,&pin_PB01), + TIM(2,1,2,&pin_PB03), + TIM(3,2,1,&pin_PB04), + TIM(3,2,2,&pin_PB05), + TIM(4,2,1,&pin_PB06), + TIM(4,2,2,&pin_PB07), + TIM(4,2,3,&pin_PB08), + TIM(10,2,1,&pin_PB08), + TIM(4,2,4,&pin_PB09), + TIM(11,2,1,&pin_PB09), + TIM(2,1,3,&pin_PB10), + TIM(2,1,4,&pin_PB11), + TIM(12,9,1,&pin_PB14), + TIM(12,9,2,&pin_PB15), + TIM(3,2,1,&pin_PC06), + TIM(3,2,2,&pin_PC07), + TIM(3,2,3,&pin_PC08), + TIM(3,2,4,&pin_PC09), + TIM(8,3,1,&pin_PC06), + TIM(8,3,2,&pin_PC07), + TIM(8,3,3,&pin_PC08), + TIM(8,3,4,&pin_PC09), + TIM(4,2,1,&pin_PD12), + TIM(4,2,2,&pin_PD13), + TIM(4,2,3,&pin_PD14), + TIM(4,2,4,&pin_PD15), + TIM(9,3,1,&pin_PE05), + TIM(9,3,2,&pin_PE06), + TIM(1,1,1,&pin_PE09), + TIM(1,1,2,&pin_PE11), + TIM(1,1,3,&pin_PE13), + TIM(1,1,4,&pin_PE14), + TIM(10,3,1,&pin_PF06), + TIM(11,3,1,&pin_PF07), + TIM(13,9,1,&pin_PF08), + TIM(14,9,1,&pin_PF09), + TIM(5,2,1,&pin_PF03), + TIM(5,2,2,&pin_PF04), + TIM(5,2,3,&pin_PF05), + TIM(5,2,4,&pin_PF10), +}; diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h index d12bbba93e..49ba108273 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h @@ -42,4 +42,9 @@ extern const mcu_spi_mosi_obj_t mcu_spi_mosi_list[14]; extern const mcu_spi_miso_obj_t mcu_spi_miso_list[12]; extern const mcu_spi_nss_obj_t mcu_spi_nss_list[12]; +#define TIM_BANK_ARRAY_LEN 14 +TIM_TypeDef * mcu_tim_banks[14]; +#define TIM_PIN_ARRAY_LEN 60 +const mcu_tim_pin_obj_t mcu_tim_pin_list[60]; + #endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411VE_PERIPH_H \ No newline at end of file From e35eb08f1d91f4db7a65eea0987a8cdc4d1e1d65 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 28 Oct 2019 21:08:53 -0400 Subject: [PATCH 20/38] nrf: allocate two I2C on CPB --- .../mpconfigboard.mk | 7 ++++ ports/nrf/nrfx_config.h | 33 ++++++++++++++----- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk index dbb32629c6..d53e486f9d 100644 --- a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk +++ b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk @@ -24,3 +24,10 @@ NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICE_COUNT = 1 EXTERNAL_FLASH_DEVICES = "GD25Q16C" + +# Allocate two, not just one I2C peripheral for CPB, so that we have both +# on-board and off-board I2C available. +# When SPIM3 becomes available we'll be able to have two I2C and two SPI peripherals. +# We use a CFLAGS define here because there are include order issues +# if we try to include "mpconfigport.h" into nrfx_config.h . +CFLAGS += -DCIRCUITPY_NRF_NUM_I2C=2 diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h index 8fa6721e2c..cafec6aa1d 100644 --- a/ports/nrf/nrfx_config.h +++ b/ports/nrf/nrfx_config.h @@ -5,12 +5,9 @@ #define NRFX_POWER_ENABLED 1 #define NRFX_POWER_CONFIG_IRQ_PRIORITY 7 -// Turn on nrfx supported workarounds for errata in Rev1/Rev2 of nRF52832 -#ifdef NRF52832_XXAA - #define NRFX_SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED 1 -#endif - -// NOTE: THIS WORKAROUND CAUSES BLE CODE TO CRASH; tested on 2019-03-11. +// NOTE: THIS WORKAROUND CAUSES BLE CODE TO CRASH. +// It doesn't work with the SoftDevice. +// See https://devzone.nordicsemi.com/f/nordic-q-a/33982/sdk-15-software-crash-during-spi-session // Turn on nrfx supported workarounds for errata in Rev1 of nRF52840 #ifdef NRF52840_XXAA // #define NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED 1 @@ -24,11 +21,26 @@ // so out of the box TWIM0/SPIM0 and TWIM1/SPIM1 cannot be shared // between common-hal/busio/I2C.c and SPI.c. // We could write an interrupt handler that checks whether it's -// being used for SPI or I2C, but perhaps two I2C's and 1-2 SPI's are good enough for now. +// being used for SPI or I2C, but perhaps one I2C and two SPI or two I2C and one SPI +// are good enough for now. + +// CIRCUITPY_NRF_NUM_I2C is 1 or 2 to choose how many I2C (TWIM) peripherals +// to provide. +// This can go away once we have SPIM3 working: then we can have two +// I2C and two SPI. +#ifndef CIRCUITPY_NRF_NUM_I2C +#define CIRCUITPY_NRF_NUM_I2C 1 +#endif + +#if CIRCUITPY_NRF_NUM_I2C != 1 && CIRCUITPY_NRF_NUM_I2C != 2 +# error CIRCUITPY_NRF_NUM_I2C must be 1 or 2 +#endif // Enable SPIM1, SPIM2 and SPIM3 (if available) // No conflict with TWIM0. +#if CIRCUITPY_NRF_NUM_I2C == 1 #define NRFX_SPIM1_ENABLED 1 +#endif #define NRFX_SPIM2_ENABLED 1 // DON'T ENABLE SPIM3 DUE TO ANOMALY WORKAROUND FAILURE (SEE ABOVE). // #ifdef NRF52840_XXAA @@ -45,10 +57,13 @@ // QSPI #define NRFX_QSPI_ENABLED 1 -// TWI aka. I2C; enable a single bus: TWIM0 (no conflict with SPIM1 and SPIM2) +// TWI aka. I2C; always enable TWIM0 (no conflict with SPIM1 and SPIM2) #define NRFX_TWIM_ENABLED 1 #define NRFX_TWIM0_ENABLED 1 -//#define NRFX_TWIM1_ENABLED 1 + +#if CIRCUITPY_NRF_NUM_I2C == 2 +#define NRFX_TWIM1_ENABLED 1 +#endif #define NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY NRF_TWIM_FREQ_400K From 43b8d5e8ab07d9053fd55059a240891b6547626b Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 29 Oct 2019 09:58:44 -0400 Subject: [PATCH 21/38] Update I2C and SPI documentation --- shared-bindings/busio/I2C.c | 4 ++++ shared-bindings/busio/SPI.c | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c index 3bd89e2e20..50a95beb2e 100644 --- a/shared-bindings/busio/I2C.c +++ b/shared-bindings/busio/I2C.c @@ -60,6 +60,10 @@ //| :param int frequency: The clock frequency in Hertz //| :param int timeout: The maximum clock stretching timeut - (used only for bitbangio.I2C; ignored for busio.I2C) //| +//| .. note:: On the nRF52840, only one I2C object may be created, +//| except on the Circuit Playground Bluefruit, which allows two, +//| one for the onboard accelerometer, and one for offboard use. +//| STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { busio_i2c_obj_t *self = m_new_obj(busio_i2c_obj_t); self->base.type = &busio_i2c_type; diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index d47bf499a2..d1791bef3b 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -154,11 +154,12 @@ STATIC void check_for_deinit(busio_spi_obj_t *self) { //| within spec for the SAMD21. //| //| .. note:: On the nRF52840, these baudrates are available: 125kHz, 250kHz, 1MHz, 2MHz, 4MHz, -//| and 8MHz. 16MHz and 32MHz are also available, but only on the first -//| `busio.SPI` object you create. Two more ``busio.SPI`` objects can be created, but they are restricted -//| to 8MHz maximum. This is a hardware restriction: there is only one high-speed SPI peripheral. +//| and 8MHz. //| If you pick a a baudrate other than one of these, the nearest lower //| baudrate will be chosen, with a minimum of 125kHz. +//| Two SPI objects may be created, except on the Circuit Playground Bluefruit, +//| which allows only one (to allow for an additional I2C object). +//| STATIC mp_obj_t busio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits }; static const mp_arg_t allowed_args[] = { From 4de5a33a437f40638b409dbe030d3cdc9fd57775 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Tue, 29 Oct 2019 10:24:26 -0400 Subject: [PATCH 22/38] Style changes --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 109 ++++++++---------- ports/stm32f4/common-hal/pulseio/PWMOut.h | 2 +- .../peripherals/stm32f4/stm32f405xx/periph.c | 2 +- .../peripherals/stm32f4/stm32f405xx/periph.h | 4 +- 4 files changed, 55 insertions(+), 62 deletions(-) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index 86f7f67e87..dcf34e249a 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -3,7 +3,6 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Dan Halbert for Adafruit Industries * Copyright (c) 2019 Lucian Copeland for Adafruit Industries * Uses code from Micropython, Copyright (c) 2013-2016 Damien P. George * @@ -46,7 +45,13 @@ STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN]; STATIC void tim_clock_enable(uint16_t mask); STATIC void tim_clock_disable(uint16_t mask); -// Get the frequency (in Hz) +RCC->CFGR & RCC_CFGR_PPRE1 + +// Get the frequency (in Hz) of the source clock for the given timer. +// On STM32F405/407/415/417 there are 2 cases for how the clock freq is set. +// If the APB prescaler is 1, then the timer clock is equal to its respective +// APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its +// respective APB clock. See DM00031020 Rev 4, page 115. static uint32_t timer_get_source_freq(uint32_t tim_id) { uint32_t source, clk_div; if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) { @@ -68,7 +73,7 @@ static uint32_t timer_get_source_freq(uint32_t tim_id) { void pwmout_reset(void) { uint16_t never_reset_mask = 0x00; for(int i=0;ihandle.Instance) { never_reset_tim[i] = false; @@ -106,14 +109,10 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, bool variable_frequency) { if (frequency == 0 || frequency > 6000000) { mp_raise_ValueError(translate("Invalid frequency supplied")); - //return PWMOUT_INVALID_FREQUENCY; } TIM_TypeDef * TIMx; - //TODO: style/safety question, use this instead? - //uint8_t tim_num_pins = TIM_PIN_ARRAY_LEN; uint8_t tim_num = sizeof(mcu_tim_pin_list)/sizeof(*mcu_tim_pin_list); - //TODO: use an enum to make this prettier? bool tim_chan_taken = false; bool tim_taken_f_mismatch = false; bool var_freq_mismatch = false; @@ -121,21 +120,21 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, for(uint i = 0; i < tim_num; i++) { //if pin is same - if(mcu_tim_pin_list[i].pin == pin) { + if (mcu_tim_pin_list[i].pin == pin) { //check if the timer has a channel active if (reserved_tim[mcu_tim_pin_list[i].tim_index-1] != 0) { //is it the same channel? (or all channels reserved by a var-freq) - if(reserved_tim[mcu_tim_pin_list[i].tim_index-1] & 1<<(mcu_tim_pin_list[i].channel_index-1)) { + if (reserved_tim[mcu_tim_pin_list[i].tim_index-1] & 1<<(mcu_tim_pin_list[i].channel_index-1)) { tim_chan_taken = true; continue; //keep looking, might be another viable option } //If the frequencies are the same it's ok - if(tim_frequencies[mcu_tim_pin_list[i].tim_index-1] != frequency) { + if (tim_frequencies[mcu_tim_pin_list[i].tim_index-1] != frequency) { tim_taken_f_mismatch = true; continue; //keep looking } //you can't put a variable frequency on a partially reserved timer - if(variable_frequency) { + if (variable_frequency) { var_freq_mismatch = true; continue; //keep looking } @@ -148,9 +147,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, } //handle valid/invalid timer instance - //TODO: why doesn't PWM handle its own value errors like every other module? - //The samd value errors don't really fit for STM32. - if(self->tim!=NULL) { + if (self->tim!=NULL) { //create instance TIMx = mcu_tim_banks[self->tim->tim_index-1]; //reserve timer/channel @@ -162,17 +159,13 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, tim_frequencies[self->tim->tim_index-1] = frequency; } else { //no match found if (tim_chan_taken) { - mp_raise_ValueError(translate("Timer hardware is reserved")); - //return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; + mp_raise_ValueError(translate("No more timers available on this pin.")); } else if (tim_taken_f_mismatch) { - mp_raise_ValueError(translate("Frequency mismatch with existing reserved channel")); - //return PWMOUT_INVALID_FREQUENCY; + mp_raise_ValueError(translate("Frequency must be the same as as the existing PWMOut using this timer")); } else if (var_freq_mismatch) { - mp_raise_ValueError(translate("Cannot vary frequency of a partially reserved timer")); - //return PWMOUT_INVALID_FREQUENCY; //I guess? + mp_raise_ValueError(translate("Cannot vary frequency on a timer that is already in use")); } else { mp_raise_ValueError(translate("Invalid pins")); - //return PWMOUT_INVALID_PIN; } } @@ -197,7 +190,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); uint32_t period = PWM_MAX_FREQ/frequency; - //TODO: remove before merging. + //Used for Debugging // mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); // mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); // mp_printf(&mp_plat_print, "Timer Freq: %d\n", source_freq/(source_freq / PWM_MAX_FREQ)); @@ -214,8 +207,8 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, self->handle.Init.RepetitionCounter = 0; //only run init if this is the first instance of this timer - if(first_time_setup) { - if(HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { + if (first_time_setup) { + if (HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { mp_raise_ValueError(translate("Timer Init Error")); } } @@ -228,10 +221,10 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, self->chan_handle.OCNPolarity = TIM_OCNPOLARITY_LOW; // needed for TIM1 and TIM8 self->chan_handle.OCIdleState = TIM_OCIDLESTATE_SET; // needed for TIM1 and TIM8 self->chan_handle.OCNIdleState = TIM_OCNIDLESTATE_SET; // needed for TIM1 and TIM8 - if(HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { + if (HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { mp_raise_ValueError(translate("Channel Init Error")); } - if(HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { + if (HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { mp_raise_ValueError(translate("Error starting PWM")); } @@ -251,7 +244,7 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { return; } //var freq shuts down entire timer, others just their channel - if(self->variable_frequency) { + if (self->variable_frequency) { reserved_tim[self->tim->tim_index-1] = 0x00; } else { reserved_tim[self->tim->tim_index-1] &= ~(1<tim->channel_index); @@ -271,7 +264,7 @@ void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16 uint16_t duty = duty_cycle/655; uint32_t period = PWM_MAX_FREQ/self->frequency; uint32_t input = (period*duty)/100; - //TODO: remove before merging + //Used for debugging //mp_printf(&mp_plat_print, "duty_cycle %d, Duty: %d, Input %d\n", duty_cycle, duty, input); __HAL_TIM_SET_COMPARE(&self->handle, self->channel, input); @@ -299,14 +292,14 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_ self->handle.Init.Prescaler = (source_freq / PWM_MAX_FREQ) - 1; // TIM runs at ~6MHz //restart everything, adjusting for new speed - if(HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { + if (HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { mp_raise_ValueError(translate("Timer Re-Init Error")); } self->chan_handle.Pulse = (period*self->duty_cycle)/100 - 1; - if(HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { + if (HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { mp_raise_ValueError(translate("Channel Re-Init Error")); } - if(HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { + if (HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { mp_raise_ValueError(translate("Error restarting PWM")); } @@ -324,80 +317,80 @@ bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self STATIC void tim_clock_enable(uint16_t mask) { #ifdef TIM1 - if(mask & 1<<0) __HAL_RCC_TIM1_CLK_ENABLE(); + if (mask & 1<<0) __HAL_RCC_TIM1_CLK_ENABLE(); #endif #ifdef TIM2 - if(mask & 1<<1) __HAL_RCC_TIM2_CLK_ENABLE(); + if (mask & 1<<1) __HAL_RCC_TIM2_CLK_ENABLE(); #endif #ifdef TIM3 - if(mask & 1<<2) __HAL_RCC_TIM3_CLK_ENABLE(); + if (mask & 1<<2) __HAL_RCC_TIM3_CLK_ENABLE(); #endif #ifdef TIM4 - if(mask & 1<<3) __HAL_RCC_TIM4_CLK_ENABLE(); + if (mask & 1<<3) __HAL_RCC_TIM4_CLK_ENABLE(); #endif #ifdef TIM5 - if(mask & 1<<4) __HAL_RCC_TIM5_CLK_ENABLE(); + if (mask & 1<<4) __HAL_RCC_TIM5_CLK_ENABLE(); #endif //6 and 7 are reserved ADC timers #ifdef TIM8 - if(mask & 1<<7) __HAL_RCC_TIM8_CLK_ENABLE(); + if (mask & 1<<7) __HAL_RCC_TIM8_CLK_ENABLE(); #endif #ifdef TIM9 - if(mask & 1<<8) __HAL_RCC_TIM9_CLK_ENABLE(); + if (mask & 1<<8) __HAL_RCC_TIM9_CLK_ENABLE(); #endif #ifdef TIM10 - if(mask & 1<<9) __HAL_RCC_TIM10_CLK_ENABLE(); + if (mask & 1<<9) __HAL_RCC_TIM10_CLK_ENABLE(); #endif #ifdef TIM11 - if(mask & 1<<10) __HAL_RCC_TIM11_CLK_ENABLE(); + if (mask & 1<<10) __HAL_RCC_TIM11_CLK_ENABLE(); #endif #ifdef TIM12 - if(mask & 1<<11) __HAL_RCC_TIM12_CLK_ENABLE(); + if (mask & 1<<11) __HAL_RCC_TIM12_CLK_ENABLE(); #endif #ifdef TIM13 - if(mask & 1<<12) __HAL_RCC_TIM13_CLK_ENABLE(); + if (mask & 1<<12) __HAL_RCC_TIM13_CLK_ENABLE(); #endif #ifdef TIM14 - if(mask & 1<<13) __HAL_RCC_TIM14_CLK_ENABLE(); + if (mask & 1<<13) __HAL_RCC_TIM14_CLK_ENABLE(); #endif } STATIC void tim_clock_disable(uint16_t mask) { #ifdef TIM1 - if(mask & 1<<0) __HAL_RCC_TIM1_CLK_DISABLE(); + if (mask & 1<<0) __HAL_RCC_TIM1_CLK_DISABLE(); #endif #ifdef TIM2 - if(mask & 1<<1) __HAL_RCC_TIM2_CLK_DISABLE(); + if (mask & 1<<1) __HAL_RCC_TIM2_CLK_DISABLE(); #endif #ifdef TIM3 - if(mask & 1<<2) __HAL_RCC_TIM3_CLK_DISABLE(); + if (mask & 1<<2) __HAL_RCC_TIM3_CLK_DISABLE(); #endif #ifdef TIM4 - if(mask & 1<<3) __HAL_RCC_TIM4_CLK_DISABLE(); + if (mask & 1<<3) __HAL_RCC_TIM4_CLK_DISABLE(); #endif #ifdef TIM5 - if(mask & 1<<4) __HAL_RCC_TIM5_CLK_DISABLE(); + if (mask & 1<<4) __HAL_RCC_TIM5_CLK_DISABLE(); #endif //6 and 7 are reserved ADC timers #ifdef TIM8 - if(mask & 1<<7) __HAL_RCC_TIM8_CLK_DISABLE(); + if (mask & 1<<7) __HAL_RCC_TIM8_CLK_DISABLE(); #endif #ifdef TIM9 - if(mask & 1<<8) __HAL_RCC_TIM9_CLK_DISABLE(); + if (mask & 1<<8) __HAL_RCC_TIM9_CLK_DISABLE(); #endif #ifdef TIM10 - if(mask & 1<<9) __HAL_RCC_TIM10_CLK_DISABLE(); + if (mask & 1<<9) __HAL_RCC_TIM10_CLK_DISABLE(); #endif #ifdef TIM11 - if(mask & 1<<10) __HAL_RCC_TIM11_CLK_DISABLE(); + if (mask & 1<<10) __HAL_RCC_TIM11_CLK_DISABLE(); #endif #ifdef TIM12 - if(mask & 1<<11) __HAL_RCC_TIM12_CLK_DISABLE(); + if (mask & 1<<11) __HAL_RCC_TIM12_CLK_DISABLE(); #endif #ifdef TIM13 - if(mask & 1<<12) __HAL_RCC_TIM13_CLK_DISABLE(); + if (mask & 1<<12) __HAL_RCC_TIM13_CLK_DISABLE(); #endif #ifdef TIM14 - if(mask & 1<<13) __HAL_RCC_TIM14_CLK_DISABLE(); + if (mask & 1<<13) __HAL_RCC_TIM14_CLK_DISABLE(); #endif -} \ No newline at end of file +} diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.h b/ports/stm32f4/common-hal/pulseio/PWMOut.h index a7784204ce..ed9561deee 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.h +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2017 Lucian Copeland for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c index 859a3d0c23..67faacdf6b 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c @@ -148,7 +148,7 @@ const mcu_tim_pin_obj_t mcu_tim_pin_list[56] = { TIM(11,3,1,&pin_PF07), TIM(13,9,1,&pin_PF08), TIM(14,9,1,&pin_PF09), - // TIM(12,9,1,&pin_PH06), + // TIM(12,9,1,&pin_PH06), //TODO: include these when pin map is expanded // TIM(12,9,2,&pin_PH09), // TIM(5,2,1,&pin_PH10), // TIM(5,2,2,&pin_PH11), diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h index 43e6644507..89298cdab4 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h @@ -42,9 +42,9 @@ extern const mcu_spi_miso_obj_t mcu_spi_miso_list[6]; extern const mcu_spi_nss_obj_t mcu_spi_nss_list[6]; #define TIM_BANK_ARRAY_LEN 14 -TIM_TypeDef * mcu_tim_banks[14]; #define TIM_PIN_ARRAY_LEN 56 -const mcu_tim_pin_obj_t mcu_tim_pin_list[56]; +TIM_TypeDef * mcu_tim_banks[TIM_BANK_ARRAY_LEN]; +const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN]; #endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F405XX_PERIPH_H \ No newline at end of file From 6b0cb87cbf3259e86100c2417e35c6066b13c0eb Mon Sep 17 00:00:00 2001 From: Hierophect Date: Tue, 29 Oct 2019 17:17:26 -0400 Subject: [PATCH 23/38] Dynamic prescaler adjustment, adjust pulse resolution --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 69 ++++++++++++----------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index dcf34e249a..a371e671e7 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -35,7 +35,7 @@ #include "stm32f4xx_hal.h" #include "common-hal/microcontroller/Pin.h" -#define PWM_MAX_FREQ 6000000 +#define PULSE_RESOLUTION 256 //8 bit #define ALL_CLOCKS 0xFFFF STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN]; @@ -45,8 +45,6 @@ STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN]; STATIC void tim_clock_enable(uint16_t mask); STATIC void tim_clock_disable(uint16_t mask); -RCC->CFGR & RCC_CFGR_PPRE1 - // Get the frequency (in Hz) of the source clock for the given timer. // On STM32F405/407/415/417 there are 2 cases for how the clock freq is set. // If the APB prescaler is 1, then the timer clock is equal to its respective @@ -107,10 +105,6 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, uint16_t duty, uint32_t frequency, bool variable_frequency) { - if (frequency == 0 || frequency > 6000000) { - mp_raise_ValueError(translate("Invalid frequency supplied")); - } - TIM_TypeDef * TIMx; uint8_t tim_num = sizeof(mcu_tim_pin_list)/sizeof(*mcu_tim_pin_list); bool tim_chan_taken = false; @@ -189,19 +183,25 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, } uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); - uint32_t period = PWM_MAX_FREQ/frequency; + if (frequency == 0 || frequency * PULSE_RESOLUTION > (source_freq)) { + mp_raise_ValueError(translate("Invalid frequency supplied")); + } + uint32_t prescaler = source_freq/(frequency*PULSE_RESOLUTION); + uint32_t period = PULSE_RESOLUTION; + uint32_t input = (duty*PULSE_RESOLUTION)/65535; //Used for Debugging - // mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); - // mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); - // mp_printf(&mp_plat_print, "Timer Freq: %d\n", source_freq/(source_freq / PWM_MAX_FREQ)); - // mp_printf(&mp_plat_print, "Actual Freq: %d\n", (source_freq/(source_freq / PWM_MAX_FREQ))/period); - // mp_printf(&mp_plat_print, "Duty: %d\n", duty); - // mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index); + mp_printf(&mp_plat_print, "Duty:%d, Pulses:%d\n", duty,input); + mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); + mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); + mp_printf(&mp_plat_print, "Prescaler %d, Timer Freq: %d\n", prescaler, source_freq/prescaler); + mp_printf(&mp_plat_print, "Output Freq: %d\n", (source_freq/prescaler)/period); + mp_printf(&mp_plat_print, "Duty: %d\n", duty); + mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index); //Timer init self->handle.Instance = TIMx; self->handle.Init.Period = period - 1; - self->handle.Init.Prescaler = (source_freq / PWM_MAX_FREQ) - 1; // TIM runs at ~6MHz + self->handle.Init.Prescaler = prescaler - 1; self->handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; self->handle.Init.CounterMode = TIM_COUNTERMODE_UP; self->handle.Init.RepetitionCounter = 0; @@ -209,23 +209,23 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, //only run init if this is the first instance of this timer if (first_time_setup) { if (HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { - mp_raise_ValueError(translate("Timer Init Error")); + mp_raise_ValueError(translate("Could not initialize timer")); } } //Channel/PWM init self->chan_handle.OCMode = TIM_OCMODE_PWM1; - self->chan_handle.Pulse = (period*duty)/100 - 1; + self->chan_handle.Pulse = input; //-1? self->chan_handle.OCPolarity = TIM_OCPOLARITY_LOW; self->chan_handle.OCFastMode = TIM_OCFAST_DISABLE; self->chan_handle.OCNPolarity = TIM_OCNPOLARITY_LOW; // needed for TIM1 and TIM8 self->chan_handle.OCIdleState = TIM_OCIDLESTATE_SET; // needed for TIM1 and TIM8 self->chan_handle.OCNIdleState = TIM_OCNIDLESTATE_SET; // needed for TIM1 and TIM8 if (HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { - mp_raise_ValueError(translate("Channel Init Error")); + mp_raise_ValueError(translate("Could not initialize channel")); } if (HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { - mp_raise_ValueError(translate("Error starting PWM")); + mp_raise_ValueError(translate("Could not start PWM")); } self->variable_frequency = variable_frequency; @@ -261,14 +261,12 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { } void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) { - uint16_t duty = duty_cycle/655; - uint32_t period = PWM_MAX_FREQ/self->frequency; - uint32_t input = (period*duty)/100; + uint32_t input = (duty_cycle*PULSE_RESOLUTION)/65535; //Used for debugging //mp_printf(&mp_plat_print, "duty_cycle %d, Duty: %d, Input %d\n", duty_cycle, duty, input); __HAL_TIM_SET_COMPARE(&self->handle, self->channel, input); - self->duty_cycle = duty; + self->duty_cycle = duty_cycle; } uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { @@ -276,31 +274,38 @@ uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { } void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency) { - if (frequency == 0 || frequency > 6000000) { - mp_raise_ValueError(translate("Invalid PWM frequency")); - } + //don't halt setup for the same frequency if (frequency == self->frequency) return; + //calculate new values uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); - uint32_t period = PWM_MAX_FREQ/frequency; + if (frequency == 0 || frequency*PULSE_RESOLUTION > (source_freq)) { + mp_raise_ValueError(translate("Invalid frequency supplied")); + } + uint32_t prescaler = source_freq/(frequency*PULSE_RESOLUTION); + uint32_t period = PULSE_RESOLUTION; + //this shouldn't ever exceed 0xffff*0xffff = 0xfffe0001, so it won't integer overflow. + uint32_t input = (self->duty_cycle*PULSE_RESOLUTION)/65535; //shut down HAL_TIM_PWM_Stop(&self->handle, self->channel); //Only change altered values self->handle.Init.Period = period - 1; - self->handle.Init.Prescaler = (source_freq / PWM_MAX_FREQ) - 1; // TIM runs at ~6MHz + self->handle.Init.Prescaler = prescaler - 1; //restart everything, adjusting for new speed if (HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { - mp_raise_ValueError(translate("Timer Re-Init Error")); + mp_raise_ValueError(translate("Could not re-init timer")); } - self->chan_handle.Pulse = (period*self->duty_cycle)/100 - 1; + + self->chan_handle.Pulse = input; + if (HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { - mp_raise_ValueError(translate("Channel Re-Init Error")); + mp_raise_ValueError(translate("Could not re-init channel")); } if (HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { - mp_raise_ValueError(translate("Error restarting PWM")); + mp_raise_ValueError(translate("Could not restart PWM")); } tim_frequencies[self->tim->tim_index-1] = frequency; From 1e869d1334640d9fc01f872bae965f2f4e28da89 Mon Sep 17 00:00:00 2001 From: ladyada Date: Tue, 29 Oct 2019 21:14:45 -0400 Subject: [PATCH 24/38] switch to 8-bit mode - tested on hardware! --- .../atmel-samd/boards/pyportal_titano/board.c | 21 ++++++++----------- .../boards/pyportal_titano/mpconfigboard.h | 1 - .../atmel-samd/boards/pyportal_titano/pins.c | 9 -------- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/ports/atmel-samd/boards/pyportal_titano/board.c b/ports/atmel-samd/boards/pyportal_titano/board.c index a18bb380bb..a99246a155 100644 --- a/ports/atmel-samd/boards/pyportal_titano/board.c +++ b/ports/atmel-samd/boards/pyportal_titano/board.c @@ -80,18 +80,15 @@ uint8_t display_init_sequence[] = { }; void board_init(void) { - busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus; - common_hal_busio_spi_construct(spi, &pin_PA13, &pin_PA12, &pin_PA14); - common_hal_busio_spi_never_reset(spi); - - displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus; - bus->base.type = &displayio_fourwire_type; - common_hal_displayio_fourwire_construct(bus, - spi, - &pin_PB05, // TFT_DC Command or data - &pin_PB06, // TFT_CS Chip select - &pin_PA00, // TFT_RST Reset - 24000000); + displayio_parallelbus_obj_t* bus = &displays[0].parallel_bus; + bus->base.type = &displayio_parallelbus_type; + common_hal_displayio_parallelbus_construct(bus, + &pin_PA16, // Data0 + &pin_PB05, // Command or data + &pin_PB06, // Chip select + &pin_PB09, // Write + &pin_PB04, // Read + &pin_PA00); // Reset displayio_display_obj_t* display = &displays[0].display; display->base.type = &displayio_display_type; diff --git a/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h index 91c1188108..f2af07371c 100644 --- a/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h +++ b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h @@ -3,7 +3,6 @@ #define CIRCUITPY_MCU_FAMILY samd51 - #define MICROPY_HW_LED_STATUS (&pin_PA27) #define MICROPY_HW_NEOPIXEL (&pin_PB22) diff --git a/ports/atmel-samd/boards/pyportal_titano/pins.c b/ports/atmel-samd/boards/pyportal_titano/pins.c index 6bc0a504a4..14699a209d 100644 --- a/ports/atmel-samd/boards/pyportal_titano/pins.c +++ b/ports/atmel-samd/boards/pyportal_titano/pins.c @@ -80,15 +80,6 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, - // TFT control pins - {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_LITE), MP_ROM_PTR(&pin_PB31)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MOSI), MP_ROM_PTR(&pin_PA12)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_SCK), MP_ROM_PTR(&pin_PA13)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MISO), MP_ROM_PTR(&pin_PA14)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RST), MP_ROM_PTR(&pin_PA00)}, - {MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_PB06)}, - {MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_PB05)}, - { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); From d2b613134dc43851c88101ce735a558e1cf88773 Mon Sep 17 00:00:00 2001 From: ladyada Date: Tue, 29 Oct 2019 22:53:44 -0400 Subject: [PATCH 25/38] we should use native rotation, and tweak madctl (not done yet) --- ports/atmel-samd/boards/pyportal_titano/board.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/atmel-samd/boards/pyportal_titano/board.c b/ports/atmel-samd/boards/pyportal_titano/board.c index a99246a155..a53497cdec 100644 --- a/ports/atmel-samd/boards/pyportal_titano/board.c +++ b/ports/atmel-samd/boards/pyportal_titano/board.c @@ -74,7 +74,7 @@ uint8_t display_init_sequence[] = { 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b, 0x42, 0x3A, 0x27, 0x1B, 0x08, 0x09, 0x03, 0x00, 0x01, 0x3a, 1, 0x55, - 0x36, 1, 0x00, + 0x36, 1, 0xA8, 0x11, DELAY, 150/5, // Exit Sleep, then delay 150 ms 0x29, DELAY, 50/5 }; @@ -98,7 +98,7 @@ void board_init(void) { 320, // Height 0, // column start 0, // row start - 270, // rotation + 0, // rotation 16, // Color depth false, // grayscale false, // pixels_in_byte_share_row (unused for depths > 8) From bb8046dbb3daa1185df7a73826946c03459856d3 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Wed, 30 Oct 2019 10:00:50 -0400 Subject: [PATCH 26/38] remove debug messages --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index a371e671e7..ef06b1ee6a 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -190,13 +190,13 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, uint32_t period = PULSE_RESOLUTION; uint32_t input = (duty*PULSE_RESOLUTION)/65535; //Used for Debugging - mp_printf(&mp_plat_print, "Duty:%d, Pulses:%d\n", duty,input); - mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); - mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); - mp_printf(&mp_plat_print, "Prescaler %d, Timer Freq: %d\n", prescaler, source_freq/prescaler); - mp_printf(&mp_plat_print, "Output Freq: %d\n", (source_freq/prescaler)/period); - mp_printf(&mp_plat_print, "Duty: %d\n", duty); - mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index); + // mp_printf(&mp_plat_print, "Duty:%d, Pulses:%d\n", duty,input); + // mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); + // mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); + // mp_printf(&mp_plat_print, "Prescaler %d, Timer Freq: %d\n", prescaler, source_freq/prescaler); + // mp_printf(&mp_plat_print, "Output Freq: %d\n", (source_freq/prescaler)/period); + // mp_printf(&mp_plat_print, "Duty: %d\n", duty); + // mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index); //Timer init self->handle.Instance = TIMx; From ab3da3071c745a201f6a4d2e18aec331a986a631 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 31 Oct 2019 10:11:47 -0400 Subject: [PATCH 27/38] flip MADCTL BGR bit to reflect RGB colors --- ports/atmel-samd/boards/pyportal_titano/board.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/atmel-samd/boards/pyportal_titano/board.c b/ports/atmel-samd/boards/pyportal_titano/board.c index a53497cdec..feeb89e36e 100644 --- a/ports/atmel-samd/boards/pyportal_titano/board.c +++ b/ports/atmel-samd/boards/pyportal_titano/board.c @@ -74,7 +74,7 @@ uint8_t display_init_sequence[] = { 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b, 0x42, 0x3A, 0x27, 0x1B, 0x08, 0x09, 0x03, 0x00, 0x01, 0x3a, 1, 0x55, - 0x36, 1, 0xA8, + 0x36, 1, 0xA0, 0x11, DELAY, 150/5, // Exit Sleep, then delay 150 ms 0x29, DELAY, 50/5 }; From 2f04c5891faabc2e0e27c3ad21f652f72ab6871d Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 31 Oct 2019 14:11:50 -0400 Subject: [PATCH 28/38] flip it around --- ports/atmel-samd/boards/pyportal_titano/board.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/atmel-samd/boards/pyportal_titano/board.c b/ports/atmel-samd/boards/pyportal_titano/board.c index feeb89e36e..828ceebc4e 100644 --- a/ports/atmel-samd/boards/pyportal_titano/board.c +++ b/ports/atmel-samd/boards/pyportal_titano/board.c @@ -74,7 +74,7 @@ uint8_t display_init_sequence[] = { 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b, 0x42, 0x3A, 0x27, 0x1B, 0x08, 0x09, 0x03, 0x00, 0x01, 0x3a, 1, 0x55, - 0x36, 1, 0xA0, + 0x36, 1, 0x60, 0x11, DELAY, 150/5, // Exit Sleep, then delay 150 ms 0x29, DELAY, 50/5 }; From 0a1a12b86791eca5cc10fb51884bad10c2402b19 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Thu, 31 Oct 2019 16:59:44 -0400 Subject: [PATCH 29/38] Revise PWM period generation algorithm to match other ports --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 49 +++++++++++++++++------ ports/stm32f4/common-hal/pulseio/PWMOut.h | 1 + 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index ef06b1ee6a..44ecdc5858 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -35,7 +35,6 @@ #include "stm32f4xx_hal.h" #include "common-hal/microcontroller/Pin.h" -#define PULSE_RESOLUTION 256 //8 bit #define ALL_CLOCKS 0xFFFF STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN]; @@ -183,12 +182,21 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, } uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); - if (frequency == 0 || frequency * PULSE_RESOLUTION > (source_freq)) { + uint32_t prescaler = 0; + uint32_t period = 0; + + for (int i=0; i<32767;i++) { + period = source_freq/(i*frequency); + if (period <= 65535 && period>=2) { + prescaler = i; + break; + } + } + if (prescaler == 0) { mp_raise_ValueError(translate("Invalid frequency supplied")); } - uint32_t prescaler = source_freq/(frequency*PULSE_RESOLUTION); - uint32_t period = PULSE_RESOLUTION; - uint32_t input = (duty*PULSE_RESOLUTION)/65535; + uint32_t input = (duty*period)/65535; + //Used for Debugging // mp_printf(&mp_plat_print, "Duty:%d, Pulses:%d\n", duty,input); // mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); @@ -231,6 +239,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, self->variable_frequency = variable_frequency; self->frequency = frequency; self->duty_cycle = duty; + self->period = period; return PWMOUT_OK; } @@ -261,7 +270,7 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { } void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) { - uint32_t input = (duty_cycle*PULSE_RESOLUTION)/65535; + uint32_t input = (duty_cycle*self->period)/65535; //Used for debugging //mp_printf(&mp_plat_print, "duty_cycle %d, Duty: %d, Input %d\n", duty_cycle, duty, input); __HAL_TIM_SET_COMPARE(&self->handle, self->channel, input); @@ -277,15 +286,30 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_ //don't halt setup for the same frequency if (frequency == self->frequency) return; - //calculate new values uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); - if (frequency == 0 || frequency*PULSE_RESOLUTION > (source_freq)) { + uint32_t prescaler = 0; + uint32_t period = 0; + + for (int i=0; i<32767;i++) { + period = source_freq/(i*frequency); + if (period <= 65535 && period>=2) { + prescaler = i; + break; + } + } + if (prescaler == 0) { mp_raise_ValueError(translate("Invalid frequency supplied")); } - uint32_t prescaler = source_freq/(frequency*PULSE_RESOLUTION); - uint32_t period = PULSE_RESOLUTION; - //this shouldn't ever exceed 0xffff*0xffff = 0xfffe0001, so it won't integer overflow. - uint32_t input = (self->duty_cycle*PULSE_RESOLUTION)/65535; + + uint32_t input = (self->duty_cycle*period)/65535; + + //debugging output + // mp_printf(&mp_plat_print, "Duty:%d, Pulses:%d\n", self->duty_cycle,input); + // mp_printf(&mp_plat_print, "Period: %d\n", period); + // mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); + // mp_printf(&mp_plat_print, "Prescaler %d, Timer Freq: %d\n", prescaler, source_freq/prescaler); + // mp_printf(&mp_plat_print, "Output Freq: %d\n", (source_freq/prescaler)/period); + // mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index); //shut down HAL_TIM_PWM_Stop(&self->handle, self->channel); @@ -310,6 +334,7 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_ tim_frequencies[self->tim->tim_index-1] = frequency; self->frequency = frequency; + self->period = period; } uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) { diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.h b/ports/stm32f4/common-hal/pulseio/PWMOut.h index ed9561deee..c259d867e8 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.h +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.h @@ -43,6 +43,7 @@ typedef struct { bool variable_frequency: 1; uint16_t duty_cycle; uint32_t frequency; + uint32_t period; } pulseio_pwmout_obj_t; void pwmout_reset(void); From e4803a7973afff1a33e6bb674cfa05a7942ef541 Mon Sep 17 00:00:00 2001 From: retoc Date: Fri, 1 Nov 2019 00:09:43 +0100 Subject: [PATCH 30/38] added german translation --- locale/de_DE.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/de_DE.po b/locale/de_DE.po index b790e86bdf..971687d19f 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -737,7 +737,7 @@ msgstr "" #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c msgid "Frequency captured is above capability. Capture Paused." -msgstr "" +msgstr "Die aufgezeichnete Frequenz liegt über der Leistungsgrenze. Aufnahme angehalten." #: shared-bindings/bitbangio/I2C.c shared-bindings/bitbangio/SPI.c #: shared-bindings/busio/I2C.c shared-bindings/busio/SPI.c From 99fe905039a3f191ddb8072fee8094b05dbe7d51 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 1 Nov 2019 13:37:36 -0400 Subject: [PATCH 31/38] Reduce DotStar status brightness; macros for status colors --- supervisor/shared/rgb_led_colors.h | 24 +++++++++++++++--------- supervisor/shared/rgb_led_status.c | 2 +- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/supervisor/shared/rgb_led_colors.h b/supervisor/shared/rgb_led_colors.h index 48994ad62c..c723fbab36 100644 --- a/supervisor/shared/rgb_led_colors.h +++ b/supervisor/shared/rgb_led_colors.h @@ -1,12 +1,18 @@ -#define BLACK 0x000000 -#define GREEN 0x003000 -#define BLUE 0x000030 -#define CYAN 0x003030 -#define RED 0x300000 -#define ORANGE 0x302000 -#define YELLOW 0x303000 -#define PURPLE 0x300030 -#define WHITE 0x303030 + +#define COLOR(r, g, b) (((r) << 16) | ((g) << 8) | (b)) +// For brightness == 255 (full). This will be adjusted downward for various different RGB indicators, +// which vary in brightness. +#define INTENSITY (0x30) + +#define BLACK COLOR(0, 0, 0) +#define GREEN COLOR(0, INTENSITY, 0) +#define BLUE COLOR(0, 0, INTENSITY) +#define CYAN COLOR(0, INTENSITY, INTENSITY) +#define RED COLOR(INTENSITY, 0, 0) +#define ORANGE COLOR(INTENSITY, INTENSITY*2/3, 0) +#define YELLOW COLOR(INTENSITY, INTENSITY, 0) +#define PURPLE COLOR(INTENSITY, 0, INTENSITY) +#define WHITE COLOR(INTENSITY, INTENSITY, INTENSITY) #define BOOT_RUNNING BLUE #define MAIN_RUNNING GREEN diff --git a/supervisor/shared/rgb_led_status.c b/supervisor/shared/rgb_led_status.c index ebb20b4cc1..05df4c628a 100644 --- a/supervisor/shared/rgb_led_status.c +++ b/supervisor/shared/rgb_led_status.c @@ -38,7 +38,7 @@ static digitalio_digitalinout_obj_t status_neopixel; #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) -uint8_t rgb_status_brightness = 255; +uint8_t rgb_status_brightness = 50; #define APA102_BUFFER_LENGTH 12 static uint8_t status_apa102_color[APA102_BUFFER_LENGTH] = {0, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff}; From fe47eba97fffb6a689592158bf6f97959c2ec798 Mon Sep 17 00:00:00 2001 From: jepler Date: Fri, 1 Nov 2019 16:23:35 -0500 Subject: [PATCH 32/38] nRF: Handle SPEAKER_ENABLE_PIN .. the existing code, which was never activated by the preprocessor, wasn't quite right. --- ports/nrf/common-hal/microcontroller/Pin.c | 24 ++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/ports/nrf/common-hal/microcontroller/Pin.c b/ports/nrf/common-hal/microcontroller/Pin.c index 3cee784b63..2973a70e91 100644 --- a/ports/nrf/common-hal/microcontroller/Pin.c +++ b/ports/nrf/common-hal/microcontroller/Pin.c @@ -25,6 +25,7 @@ */ #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/DigitalInOut.h" #include "nrf_gpio.h" #include "py/mphal.h" @@ -47,6 +48,19 @@ bool speaker_enable_in_use; STATIC uint32_t claimed_pins[GPIO_COUNT]; STATIC uint32_t never_reset_pins[GPIO_COUNT]; +STATIC void reset_speaker_enable_pin(void) { +#ifdef SPEAKER_ENABLE_PIN + speaker_enable_in_use = false; + nrf_gpio_cfg(SPEAKER_ENABLE_PIN->number, + NRF_GPIO_PIN_DIR_OUTPUT, + NRF_GPIO_PIN_INPUT_DISCONNECT, + NRF_GPIO_PIN_NOPULL, + NRF_GPIO_PIN_H0H1, + NRF_GPIO_PIN_NOSENSE); + nrf_gpio_pin_write(SPEAKER_ENABLE_PIN->number, false); +#endif +} + void reset_all_pins(void) { for (size_t i = 0; i < GPIO_COUNT; i++) { claimed_pins[i] = never_reset_pins[i]; @@ -68,10 +82,7 @@ void reset_all_pins(void) { #endif // After configuring SWD because it may be shared. - #ifdef SPEAKER_ENABLE_PIN - speaker_enable_in_use = false; - // TODO set pin to out and turn off. - #endif + reset_speaker_enable_pin(); } // Mark pin as free and return it to a quiescent state. @@ -104,10 +115,7 @@ void reset_pin_number(uint8_t pin_number) { #ifdef SPEAKER_ENABLE_PIN if (pin_number == SPEAKER_ENABLE_PIN->number) { - speaker_enable_in_use = false; - common_hal_digitalio_digitalinout_switch_to_output(SPEAKER_ENABLE_PIN, true, DRIVE_MODE_PUSH_PULL); - nrf_gpio_pin_dir_set(pin_number, NRF_GPIO_PIN_DIR_OUTPUT); - nrf_gpio_pin_write(pin_number, false); + reset_speaker_enable_pin(); } #endif } From 2bdccf03a722fc1bdb0434e96361d3d8acd0ca09 Mon Sep 17 00:00:00 2001 From: jepler Date: Fri, 1 Nov 2019 16:25:34 -0500 Subject: [PATCH 33/38] cpb: define the SPEAKER_ENABLE_PIN This allows the board to disable the onboard speaker until explicitly enabled in user code. Testing performed on a CPB: * Touching the AUDIO pin with a fingertip no longer generates noise/buzz * Generating a waveform with `simpleio.tone` produces no sound by default * When the board.SPEAKER_ENABLE is configured as a digital output and set True, `simpleio.tone` does produce sound Note that while guides should include information about SPEAKER_ENABLE, it's possible that some users who omitted it could view this as a breaking change. They can fix it by simply adding code similar to speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE) speaker_enable.direction = digitalio.Direction.OUTPUT speaker_enable.value = True before using the internal speaker. Closes: #2258 --- ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h index 1e55cd0260..8c2018925e 100644 --- a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h +++ b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h @@ -70,3 +70,5 @@ #define DEFAULT_UART_BUS_RX (&pin_P0_30) #define DEFAULT_UART_BUS_TX (&pin_P0_14) + +#define SPEAKER_ENABLE_PIN (&pin_P1_04) From 85a648224fea027eb3635b7a3746cd6c12d738a6 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 2 Nov 2019 22:47:03 -0400 Subject: [PATCH 34/38] Check for no pullups on I2C on nrf; give arduino nano 33 ble two I2C devices --- ports/atmel-samd/common-hal/busio/I2C.c | 1 + .../arduino_nano_33_ble/mpconfigboard.mk | 7 +++++ ports/nrf/common-hal/busio/I2C.c | 29 +++++++++++++++---- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index cdc616bbc8..b0e5714a79 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -116,6 +116,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, if (i2c_m_sync_set_baudrate(&self->i2c_desc, 0, frequency / 1000) != ERR_NONE) { reset_pin_number(sda->number); reset_pin_number(scl->number); + common_hal_busio_i2c_deinit(self); mp_raise_ValueError(translate("Unsupported baudrate")); } diff --git a/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.mk b/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.mk index 7a8e883f47..9a875ac442 100644 --- a/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.mk +++ b/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.mk @@ -22,3 +22,10 @@ endif NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 INTERNAL_FLASH_FILESYSTEM = 1 + +# Allocate two, not just one I2C peripheral, so that we have both +# on-board and off-board I2C available. +# When SPIM3 becomes available we'll be able to have two I2C and two SPI peripherals. +# We use a CFLAGS define here because there are include order issues +# if we try to include "mpconfigport.h" into nrfx_config.h . +CFLAGS += -DCIRCUITPY_NRF_NUM_I2C=2 diff --git a/ports/nrf/common-hal/busio/I2C.c b/ports/nrf/common-hal/busio/I2C.c index 71835d16ad..8a2ebde3bd 100644 --- a/ports/nrf/common-hal/busio/I2C.c +++ b/ports/nrf/common-hal/busio/I2C.c @@ -28,13 +28,12 @@ */ #include "shared-bindings/busio/I2C.h" +#include "shared-bindings/microcontroller/__init__.h" #include "py/mperrno.h" #include "py/runtime.h" #include "supervisor/shared/translate.h" #include "nrfx_twim.h" -#include "nrf_gpio.h" - #include "nrfx_spim.h" #include "nrf_gpio.h" @@ -107,7 +106,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t * for (size_t i = 0 ; i < MP_ARRAY_SIZE(twim_peripherals); i++) { if (!twim_peripherals[i].in_use) { self->twim_peripheral = &twim_peripherals[i]; - self->twim_peripheral->in_use = true; + // Mark it as in_use later after other validation is finished. break; } } @@ -116,10 +115,27 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t * mp_raise_ValueError(translate("All I2C peripherals are in use")); } + // Test that the pins are in a high state. (Hopefully indicating they are pulled up.) + nrf_gpio_cfg_input(scl->number, NRF_GPIO_PIN_PULLDOWN); + nrf_gpio_cfg_input(sda->number, NRF_GPIO_PIN_PULLDOWN); + + common_hal_mcu_delay_us(10); + + nrf_gpio_cfg_input(scl->number, NRF_GPIO_PIN_NOPULL); + nrf_gpio_cfg_input(sda->number, NRF_GPIO_PIN_NOPULL); + + // We must pull up within 3us to achieve 400khz. + common_hal_mcu_delay_us(3); + + if (!nrf_gpio_pin_read(sda->number) || !nrf_gpio_pin_read(scl->number)) { + reset_pin_number(sda->number); + reset_pin_number(scl->number); + mp_raise_RuntimeError(translate("SDA or SCL needs a pull up")); + } + nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG; config.scl = scl->number; config.sda = sda->number; - // change freq. only if it's less than the default 400K if (frequency < 100000) { config.frequency = NRF_TWIM_FREQ_100K; @@ -132,6 +148,8 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t * claim_pin(sda); claim_pin(scl); + // About to init. If we fail after this point, common_hal_busio_i2c_deinit() will set in_use to false. + self->twim_peripheral->in_use = true; nrfx_err_t err = nrfx_twim_init(&self->twim_peripheral->twim, &config, NULL, NULL); // A soft reset doesn't uninit the driver so we might end up with a invalid state @@ -152,8 +170,9 @@ bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { } void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { - if (common_hal_busio_i2c_deinited(self)) + if (common_hal_busio_i2c_deinited(self)) { return; + } nrfx_twim_uninit(&self->twim_peripheral->twim); From 1c4f49bb83ba38b50db412a6e30be0b25a3a2425 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Sun, 3 Nov 2019 16:33:01 -0500 Subject: [PATCH 35/38] attribution changes --- ports/stm32f4/common-hal/pulseio/PulseIn.c | 2 +- ports/stm32f4/common-hal/pulseio/PulseIn.h | 2 +- ports/stm32f4/common-hal/pulseio/PulseOut.c | 2 +- ports/stm32f4/common-hal/pulseio/PulseOut.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/stm32f4/common-hal/pulseio/PulseIn.c b/ports/stm32f4/common-hal/pulseio/PulseIn.c index 25adb7d769..068936bdd0 100644 --- a/ports/stm32f4/common-hal/pulseio/PulseIn.c +++ b/ports/stm32f4/common-hal/pulseio/PulseIn.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2019 Lucian Copeland for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/stm32f4/common-hal/pulseio/PulseIn.h b/ports/stm32f4/common-hal/pulseio/PulseIn.h index 9f4cc9f43c..2538b07ab5 100644 --- a/ports/stm32f4/common-hal/pulseio/PulseIn.h +++ b/ports/stm32f4/common-hal/pulseio/PulseIn.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2019 Lucian Copeland for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/stm32f4/common-hal/pulseio/PulseOut.c b/ports/stm32f4/common-hal/pulseio/PulseOut.c index 7e9812db69..d393afc5c6 100644 --- a/ports/stm32f4/common-hal/pulseio/PulseOut.c +++ b/ports/stm32f4/common-hal/pulseio/PulseOut.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2019 Lucian Copeland for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/stm32f4/common-hal/pulseio/PulseOut.h b/ports/stm32f4/common-hal/pulseio/PulseOut.h index 48f2bb3f1b..45823d28a4 100644 --- a/ports/stm32f4/common-hal/pulseio/PulseOut.h +++ b/ports/stm32f4/common-hal/pulseio/PulseOut.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2019 Lucian Copeland for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From ccff7e70ca91a807e1073f756ba20491f6a20c35 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Mon, 4 Nov 2019 11:30:49 -0500 Subject: [PATCH 36/38] Style changes and refactors --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 109 ++++++++-------------- 1 file changed, 41 insertions(+), 68 deletions(-) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index 44ecdc5858..16b1b5b896 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -49,7 +49,7 @@ STATIC void tim_clock_disable(uint16_t mask); // If the APB prescaler is 1, then the timer clock is equal to its respective // APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its // respective APB clock. See DM00031020 Rev 4, page 115. -static uint32_t timer_get_source_freq(uint32_t tim_id) { +STATIC uint32_t timer_get_source_freq(uint32_t tim_id) { uint32_t source, clk_div; if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) { // TIM{1,8,9,10,11} are on APB2 @@ -67,6 +67,26 @@ static uint32_t timer_get_source_freq(uint32_t tim_id) { return source; } +STATIC uint32_t timer_get_internal_duty(uint16_t duty, uint32_t period) { + //duty cycle is duty/0xFFFF fraction x (number of pulses per period) + return (duty*period)/((1<<16)-1); +} + +STATIC void timer_get_optimal_divisors(uint32_t*period, uint32_t*prescaler, + uint32_t frequency, uint32_t source_freq) { + //Find the largest possible period supported by this frequency + for (int i=0; i<(1 << 16);i++) { + *period = source_freq/(i*frequency); + if (*period < (1 << 16) && *period>=2) { + *prescaler = i; + break; + } + } + if (*prescaler == 0) { + mp_raise_ValueError(translate("Invalid frequency supplied")); + } +} + void pwmout_reset(void) { uint16_t never_reset_mask = 0x00; for(int i=0;itim = &mcu_tim_pin_list[i]; + self->tim = &l_tim; break; } } @@ -170,41 +194,14 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, GPIO_InitStruct.Alternate = self->tim->altfn_index; HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct); - //TODO: factor all of these into periph.c? tim_clock_enable(1<<(self->tim->tim_index - 1)); //translate channel into handle value - switch (self->tim->channel_index) { - case 1: self->channel = TIM_CHANNEL_1; break; - case 2: self->channel = TIM_CHANNEL_2; break; - case 3: self->channel = TIM_CHANNEL_3; break; - case 4: self->channel = TIM_CHANNEL_4; break; - } + self->channel = 4 * (self->tim->channel_index - 1); - uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); - uint32_t prescaler = 0; - uint32_t period = 0; - - for (int i=0; i<32767;i++) { - period = source_freq/(i*frequency); - if (period <= 65535 && period>=2) { - prescaler = i; - break; - } - } - if (prescaler == 0) { - mp_raise_ValueError(translate("Invalid frequency supplied")); - } - uint32_t input = (duty*period)/65535; - - //Used for Debugging - // mp_printf(&mp_plat_print, "Duty:%d, Pulses:%d\n", duty,input); - // mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); - // mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); - // mp_printf(&mp_plat_print, "Prescaler %d, Timer Freq: %d\n", prescaler, source_freq/prescaler); - // mp_printf(&mp_plat_print, "Output Freq: %d\n", (source_freq/prescaler)/period); - // mp_printf(&mp_plat_print, "Duty: %d\n", duty); - // mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index); + uint32_t prescaler = 0; //prescaler is 15 bit + uint32_t period = 0; //period is 16 bit + timer_get_optimal_divisors(&period, &prescaler,frequency,timer_get_source_freq(self->tim->tim_index)); //Timer init self->handle.Instance = TIMx; @@ -223,7 +220,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, //Channel/PWM init self->chan_handle.OCMode = TIM_OCMODE_PWM1; - self->chan_handle.Pulse = input; //-1? + self->chan_handle.Pulse = timer_get_internal_duty(duty, period); self->chan_handle.OCPolarity = TIM_OCPOLARITY_LOW; self->chan_handle.OCFastMode = TIM_OCFAST_DISABLE; self->chan_handle.OCNPolarity = TIM_OCNPOLARITY_LOW; // needed for TIM1 and TIM8 @@ -269,13 +266,10 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { } } -void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) { - uint32_t input = (duty_cycle*self->period)/65535; - //Used for debugging - //mp_printf(&mp_plat_print, "duty_cycle %d, Duty: %d, Input %d\n", duty_cycle, duty, input); - __HAL_TIM_SET_COMPARE(&self->handle, self->channel, input); - - self->duty_cycle = duty_cycle; +void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty) { + uint32_t internal_duty_cycle = timer_get_internal_duty(duty, self->period); + __HAL_TIM_SET_COMPARE(&self->handle, self->channel, internal_duty_cycle); + self->duty_cycle = duty; } uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { @@ -286,30 +280,9 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_ //don't halt setup for the same frequency if (frequency == self->frequency) return; - uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); uint32_t prescaler = 0; uint32_t period = 0; - - for (int i=0; i<32767;i++) { - period = source_freq/(i*frequency); - if (period <= 65535 && period>=2) { - prescaler = i; - break; - } - } - if (prescaler == 0) { - mp_raise_ValueError(translate("Invalid frequency supplied")); - } - - uint32_t input = (self->duty_cycle*period)/65535; - - //debugging output - // mp_printf(&mp_plat_print, "Duty:%d, Pulses:%d\n", self->duty_cycle,input); - // mp_printf(&mp_plat_print, "Period: %d\n", period); - // mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); - // mp_printf(&mp_plat_print, "Prescaler %d, Timer Freq: %d\n", prescaler, source_freq/prescaler); - // mp_printf(&mp_plat_print, "Output Freq: %d\n", (source_freq/prescaler)/period); - // mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index); + timer_get_optimal_divisors(&period, &prescaler,frequency,timer_get_source_freq(self->tim->tim_index)); //shut down HAL_TIM_PWM_Stop(&self->handle, self->channel); @@ -323,7 +296,7 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_ mp_raise_ValueError(translate("Could not re-init timer")); } - self->chan_handle.Pulse = input; + self->chan_handle.Pulse = timer_get_internal_duty(self->duty_cycle, period); if (HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { mp_raise_ValueError(translate("Could not re-init channel")); From f185b30d711f39dc441919ba52d80b6dc299bc5f Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 4 Nov 2019 20:41:54 -0500 Subject: [PATCH 37/38] Update PWMOut.h --- ports/stm32f4/common-hal/pulseio/PWMOut.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.h b/ports/stm32f4/common-hal/pulseio/PWMOut.h index c259d867e8..59fc04e5ff 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.h +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Lucian Copeland for Adafruit Industries + * Copyright (c) 2019 Lucian Copeland for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 73989dbcaf8cf28d291561811dd244a7de456dbf Mon Sep 17 00:00:00 2001 From: Thea Flowers Date: Tue, 29 Oct 2019 14:10:16 -0700 Subject: [PATCH 38/38] Add board configuration for Winterbloom Sol --- .github/workflows/build.yml | 1 + .../atmel-samd/boards/winterbloom_sol/board.c | 38 +++++++++++++++++++ .../boards/winterbloom_sol/mpconfigboard.h | 33 ++++++++++++++++ .../boards/winterbloom_sol/mpconfigboard.mk | 27 +++++++++++++ .../atmel-samd/boards/winterbloom_sol/pins.c | 15 ++++++++ supervisor/shared/external_flash/devices.h | 17 +++++++++ 6 files changed, 131 insertions(+) create mode 100644 ports/atmel-samd/boards/winterbloom_sol/board.c create mode 100644 ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.h create mode 100644 ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk create mode 100644 ports/atmel-samd/boards/winterbloom_sol/pins.c diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c393afe7d8..10c34355d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -158,6 +158,7 @@ jobs: - "trinket_m0_haxpress" - "uchip" - "ugame10" + - "winterbloom_sol" steps: - name: Set up Python 3.5 diff --git a/ports/atmel-samd/boards/winterbloom_sol/board.c b/ports/atmel-samd/boards/winterbloom_sol/board.c new file mode 100644 index 0000000000..8096b9b8ea --- /dev/null +++ b/ports/atmel-samd/boards/winterbloom_sol/board.c @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" +#include "mpconfigboard.h" + +void board_init(void) { +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.h b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.h new file mode 100644 index 0000000000..7e01e228ac --- /dev/null +++ b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.h @@ -0,0 +1,33 @@ +#define MICROPY_HW_BOARD_NAME "Winterbloom Sol" +#define MICROPY_HW_MCU_NAME "samd51j20" + +#define CIRCUITPY_MCU_FAMILY samd51 + +#define MICROPY_HW_LED_STATUS (&pin_PA23) +#define MICROPY_HW_NEOPIXEL (&pin_PB03) + +// These are pins not to reset. +// QSPI Data pins +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) +// QSPI CS, QSPI SCK and NeoPixel pin +#define MICROPY_PORT_B (PORT_PB03 | PORT_PB10 | PORT_PB11) +#define MICROPY_PORT_C (0) +#define MICROPY_PORT_D (0) + +#define AUTORESET_DELAY_MS 500 + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code +#define CIRCUITPY_INTERNAL_NVM_SIZE 8192 + +#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#define BOARD_HAS_CRYSTAL 1 + +#define DEFAULT_SPI_BUS_SCK (&pin_PA17) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB23) +#define DEFAULT_SPI_BUS_MISO (&pin_PB22) + +// USB is always used internally so skip the pin objects for it. +#define IGNORE_PIN_PA24 1 +#define IGNORE_PIN_PA25 1 diff --git a/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk new file mode 100644 index 0000000000..19917898b6 --- /dev/null +++ b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk @@ -0,0 +1,27 @@ +LD_FILE = boards/samd51x20-bootloader-external-flash.ld +# Adafruit +USB_VID = 0x239A +# Allocated for Winterbloom Sol +# https://github.com/adafruit/circuitpython/issues/2217 +USB_PID = 0x8062 +USB_PRODUCT = "Sol" +USB_MANUFACTURER = "Winterbloom" + +CHIP_VARIANT = SAMD51J20A +CHIP_FAMILY = samd51 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = W25Q32JV_IQ +LONGINT_IMPL = MPZ + +# Disable modules that are unusable on this special-purpose board. +CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_AUDIOIO = 0 +CIRCUITPY_BLEIO = 0 +CIRCUITPY_DISPLAYIO = 0 +CIRCUITPY_GAMEPAD = 0 +CIRCUITPY_I2CSLAVE = 0 +CIRCUITPY_NETWORK = 0 +CIRCUITPY_TOUCHIO = 0 +CIRCUITPY_PS2IO = 0 diff --git a/ports/atmel-samd/boards/winterbloom_sol/pins.c b/ports/atmel-samd/boards/winterbloom_sol/pins.c new file mode 100644 index 0000000000..013542d3ca --- /dev/null +++ b/ports/atmel-samd/boards/winterbloom_sol/pins.c @@ -0,0 +1,15 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB23) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB22) }, + { MP_ROM_QSTR(MP_QSTR_DAC_CS), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_G1), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_G2), MP_ROM_PTR(&pin_PA21) }, + { MP_ROM_QSTR(MP_QSTR_G3), MP_ROM_PTR(&pin_PA22) }, + { MP_ROM_QSTR(MP_QSTR_G4), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/supervisor/shared/external_flash/devices.h b/supervisor/shared/external_flash/devices.h index 05091ad8cf..08d0a78fdd 100644 --- a/supervisor/shared/external_flash/devices.h +++ b/supervisor/shared/external_flash/devices.h @@ -300,6 +300,23 @@ typedef struct { .write_status_register_split = false, \ } +// Settings for the Winbond W25Q32JV-IQ 4MiB SPI flash. +// Datasheet: https://www.mouser.com/datasheet/2/949/w25q32jv_revg_03272018_plus-1489806.pdf +#define W25Q32JV_IQ {\ + .total_size = (1 << 22), /* 4 MiB */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xef, \ + .memory_type = 0x40, \ + .capacity = 0x16, \ + .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ + .supports_qspi = true, \ + .supports_qspi_writes = true, \ + .write_status_register_split = false, \ +} + // Settings for the Winbond W25Q64JV-IM 8MiB SPI flash. Note that JV-IQ has a different .memory_type (0x40) // Datasheet: http://www.winbond.com/resource-files/w25q64jv%20revj%2003272018%20plus.pdf #define W25Q64JV_IM {\