static void templog_statemachine(void) { switch (templog_state) { case TEMPLOG_IDLE: case TEMPLOG_SLEEPING: onboard_led(ONBOARD_LED_ON); timeout_add(&templog_timeout, templog_interval * 1000, read_temp_again, NULL); ds_read(&ds, got_temp_data, NULL); templog_state = TEMPLOG_READING; onboard_led(ONBOARD_LED_OFF); break; case TEMPLOG_READING: /* timeout was triggered before */ templog_state = TEMPLOG_SLEEPING; break; case TEMPLOG_STOPPING: flash_flush_data(flash_pagepos, stop_flush_done, NULL); flash_pagepos = 0; templog_state = TEMPLOG_STOP_FLUSHING; break; case TEMPLOG_STOP_FLUSHING: templog_state = TEMPLOG_STOPPED; break; case TEMPLOG_STOPPED: break; } }
void new_data(uint8_t *data, size_t len) { onboard_led(-1); cdc_write(data, len, &loopback); cdc_read_more(&loopback); }
int set_report(enum hid_report_type type, uint8_t report_id, void **data, size_t len) { if (type != USB_HID_REPORT_TYPE_FEATURE) return (0); if (*data == NULL) *data = &feature_report; else /* transfer done */ onboard_led(ONBOARD_LED_TOGGLE); return (1); }
static void new_data(uint8_t *data, size_t len) { onboard_led(-1); cdc_write(data, len, &cdc); }
void simble_adv_start(void) { struct ble_gap_advdata advdata = { .length = 0 }; struct ble_gap_ad_flags flags = { .payload_length = 1, .type = BLE_GAP_AD_TYPE_FLAGS, .flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE, }; simble_add_advdata(&flags, &advdata); struct ble_gap_ad_name name; uint16_t namelen = sizeof(advdata); if (sd_ble_gap_device_name_get(name.name, &namelen) != NRF_SUCCESS) namelen = 0; name.type = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; name.payload_length = namelen; simble_add_advdata(&name, &advdata); sd_ble_gap_adv_data_set(advdata.data, advdata.length, NULL, 0); ble_gap_adv_params_t adv_params = { .type = BLE_GAP_ADV_TYPE_ADV_IND, .fp = BLE_GAP_ADV_FP_ANY, .interval = 0x400, }; sd_ble_gap_adv_start(&adv_params); onboard_led(ONBOARD_LED_ON); } static void simble_srv_tx_init(void) { uint16_t srv_handle; ble_uuid_t srv_uuid = {.type = BLE_UUID_TYPE_BLE, .uuid = 0x1804}; sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &srv_uuid, &srv_handle); ble_gatts_char_handles_t chr_handles; ble_gatts_char_md_t char_meta = {.char_props = {.read = 1}}; ble_uuid_t chr_uuid = {.type = BLE_UUID_TYPE_BLE, .uuid = 0x2a07}; ble_gatts_attr_md_t chr_attr_meta = { .vloc = BLE_GATTS_VLOC_STACK, }; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&chr_attr_meta.read_perm); BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&chr_attr_meta.write_perm); uint8_t tx_val = 0; ble_gatts_attr_t chr_attr = { .p_uuid = &chr_uuid, .p_attr_md = &chr_attr_meta, .init_offs = 0, .init_len = sizeof(tx_val), .max_len = sizeof(tx_val), .p_value = &tx_val, }; sd_ble_gatts_characteristic_add(srv_handle, &char_meta, &chr_attr, &chr_handles); } /* DM requires a `app_error_handler` */ void __attribute__((weak)) app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name) { app_trace_log("[simble]: err: %d, line: %d, file: %s\r\n", error_code, line_num, p_file_name); for (;;) { /* NOTHING */ } } void simble_init(const char *name) { app_trace_init(); sd_softdevice_enable(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, NULL); /* XXX assertion handler */ ble_enable_params_t ble_params = { #if defined(SD120) .gap_enable_params = { .role = BLE_GAP_ROLE_PERIPH, }, #endif .gatts_enable_params = { .service_changed = 1, }, }; sd_ble_enable(&ble_params); ble_gap_conn_sec_mode_t mode; BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&mode); sd_ble_gap_device_name_set(&mode, (const uint8_t *)name, strlen(name)); // flash storage pstorage_init(); simble_srv_tx_init(); } uint8_t simble_get_vendor_uuid_class(void) { ble_uuid128_t vendorid = {{0x13,0xb0,0xa0,0x71,0xfe,0x62,0x4c,0x01,0xaa,0x4d,0xd8,0x03,0,0,0x0b,0xd0}}; static uint8_t vendor_type = BLE_UUID_TYPE_UNKNOWN; if (vendor_type != BLE_UUID_TYPE_UNKNOWN) return (vendor_type); sd_ble_uuid_vs_add(&vendorid, &vendor_type); return (vendor_type); } void simble_srv_register(struct service_desc *s) { s->next = services; services = s; sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &s->uuid, &s->handle); for (int i = 0; i < s->char_count; ++i) { struct char_desc *c = &s->chars[i]; ble_gatts_attr_md_t cccd_md; memset(&cccd_md, 0, sizeof(cccd_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); cccd_md.vloc = BLE_GATTS_VLOC_STACK; int have_write = c->write_cb != NULL; ble_gatts_char_md_t char_meta = { .char_props = { .broadcast = 0, .read = 1, .write_wo_resp = have_write, .write = have_write, .notify = c->notify, .indicate = c->indicate, .auth_signed_wr = have_write, }, .p_char_user_desc = (uint8_t *)c->desc, .char_user_desc_size = strlen(c->desc), .char_user_desc_max_size = strlen(c->desc), .p_char_pf = c->format.format != 0 ? &c->format : NULL, .p_cccd_md = (c->notify || c->indicate) ? &cccd_md : NULL, }; ble_gatts_attr_md_t chr_attr_meta = { .vlen = 1, .vloc = BLE_GATTS_VLOC_STACK, .rd_auth = 1, .wr_auth = 1, }; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&chr_attr_meta.read_perm); if (have_write) BLE_GAP_CONN_SEC_MODE_SET_OPEN(&chr_attr_meta.write_perm); else BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&chr_attr_meta.write_perm); ble_gatts_attr_t chr_attr = { .p_uuid = &c->uuid, .p_attr_md = &chr_attr_meta, .init_offs = 0, .init_len = 0, .max_len = c->length, }; sd_ble_gatts_characteristic_add(s->handle, &char_meta, &chr_attr, &c->handles); } } void simble_srv_init(struct service_desc *s, uint8_t type, uint16_t id) { *s = (struct service_desc){ .uuid = {.type = type, .uuid = id}, .char_count = 0, }; }; void simble_srv_char_add(struct service_desc *s, struct char_desc *c, uint8_t type, uint16_t id, const char *desc, uint16_t length) { *c = (struct char_desc){ .uuid = { .type = type, .uuid = id }, .desc = desc, .length = length, };
static void blink(void *data) { onboard_led(ONBOARD_LED_TOGGLE); timeout_add(&t, 500, blink, NULL); }
void signal_led(void) { onboard_led(ONBOARD_LED_TOGGLE); }
static void dma_done(struct dma_ctx *ctx, enum dma_status status, void *cbdata) { onboard_led(status == DMA_STATUS_HALF); }