Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.c
00001 /* 00002 * Copyright (c) 2018 Bluetooth SIG 00003 * 00004 * SPDX-License-Identifier: Apache-2.0 00005 */ 00006 /* 00007 * how to set txpower 00008 * in ./subsys/bluetooth/controller/ll_sw/ctrl.c, a function naming 00009 * adv_scan_conn_configure(), it includes radio_tx_power_set(), the value 00010 * should map 00011 nRF 51: 00012 Pos4dBm 0x04 +4 dBm 00013 0dBm 0x00 0 dBm 00014 Neg4dBm 0xFC -4 dBm 00015 Neg8dBm 0xF8 -8 dBm 00016 Neg12dBm 0xF4 -12 dBm 00017 Neg16dBm 0xF0 -16 dBm 00018 Neg20dBm 0xEC -20 dBm 00019 Neg30dBm 0xD8 -30 dBm 00020 00021 nRF 52840: 00022 http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52840.ps%2Fradio.html&cp=2_0_0_5_19_13_10&anchor=register.TXPOWER 00023 00024 nRF 52832: 00025 http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fradio.html&cp=2_1_0_22_13_9&anchor=register.TXPOWER 00026 */ 00027 00028 #include <misc/printk.h> 00029 00030 #include <bluetooth/bluetooth.h> 00031 #include <bluetooth/mesh.h> 00032 #include <gpio.h> 00033 #include <board.h> 00034 #include <soc.h> 00035 #include <misc/printk.h> 00036 #include <settings/settings.h> 00037 #include <ctype.h> 00038 #include <flash.h> 00039 #include <gpio.h> 00040 #include <pwm.h> 00041 00042 #include <display/mb_display.h> 00043 00044 #include <bluetooth/mesh.h> 00045 00046 #if !defined(NODE_ADDR) 00047 #define NODE_ADDR 0x0b02 00048 #endif 00049 00050 #define CID_INTEL 0x0002 00051 #define MOD_INTEL 0x0000 00052 #define GROUP_ADDR 0xc000 00053 #define PUBLISHER_ADDR 0x000f 00054 00055 /* Model Operation Codes */ 00056 #define BT_MESH_MODEL_OP_GEN_ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01) 00057 #define BT_MESH_MODEL_OP_GEN_ONOFF_SET BT_MESH_MODEL_OP_2(0x82, 0x02) 00058 #define BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x03) 00059 #define BT_MESH_MODEL_OP_GEN_ONOFF_STATUS BT_MESH_MODEL_OP_2(0x82, 0x04) 00060 00061 /* Publication Declarations */ 00062 BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0); 00063 BT_MESH_MODEL_PUB_DEFINE(gen_onoff_pub_cli, NULL, 2 + 2); 00064 00065 /* Button debounce timeout */ 00066 #define BUTTON_DEBOUNCE_DELAY_MS 250 00067 00068 /* LED matrix scroll speed */ 00069 #define SCROLL_SPEED K_MSEC(500) 00070 00071 /* Buzzer definition, no used in this example. */ 00072 #define BUZZER_PIN EXT_P0_GPIO_PIN 00073 #define BEEP_DURATION K_MSEC(60) 00074 00075 /* Key definition, it's pre-configured, not need to do provisioning. */ 00076 static const u8_t net_key[16] = { 00077 0xf1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 00078 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 00079 }; 00080 static const u8_t dev_key[16] = { 00081 0xf1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 00082 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 00083 }; 00084 static const u8_t app_key[16] = { 00085 0xf1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 00086 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 00087 }; 00088 00089 00090 /* group address string. */ 00091 const char *groupAddress2String[] = { 00092 "Bedroom", 00093 "Living", 00094 "Dining", 00095 "Garage" 00096 }; 00097 00098 static struct device *gpio; 00099 static struct device *nvm; 00100 static struct device *pwm; 00101 00102 static struct k_work button_work; 00103 static u32_t time, last_time; 00104 00105 const u16_t net_idx; 00106 const u16_t app_idx; 00107 const u32_t iv_index; 00108 u8_t flags; 00109 u16_t addr = NODE_ADDR; 00110 u16_t groupAddress = GROUP_ADDR; 00111 00112 /* Transaction ID for Generic OnOff Set */ 00113 static u8_t trans_ID = 0; 00114 00115 /* GenericOnOffSet state */ 00116 u8_t OnOff_Value = 0; 00117 00118 /* Model Operation decleration */ 00119 static void gen_onoff_set(struct bt_mesh_model *model, 00120 struct bt_mesh_msg_ctx *ctx, 00121 struct net_buf_simple *buf); 00122 00123 static void gen_onoff_set_unack(struct bt_mesh_model *model, 00124 struct bt_mesh_msg_ctx *ctx, 00125 struct net_buf_simple *buf); 00126 00127 static void gen_onoff_get(struct bt_mesh_model *model, 00128 struct bt_mesh_msg_ctx *ctx, 00129 struct net_buf_simple *buf); 00130 00131 static void gen_onoff_status(struct bt_mesh_model *model, 00132 struct bt_mesh_msg_ctx *ctx, 00133 struct net_buf_simple *buf); 00134 static void genericOnOffSet(void); 00135 00136 00137 /* switch group address like round robin. */ 00138 u16_t board_set_target(void) 00139 { 00140 switch (groupAddress) { 00141 case GROUP_ADDR: 00142 groupAddress++; 00143 break; 00144 case (GROUP_ADDR + 3): 00145 groupAddress = GROUP_ADDR; 00146 break; 00147 default: 00148 groupAddress++; 00149 break; 00150 } 00151 00152 return groupAddress; 00153 } 00154 00155 /* Callback function for button B pressed, it's scheduled by OS, out of interrupt routine 00156 * it's safe to stay here longer. */ 00157 static void button_send_pressed(struct k_work *work) 00158 { 00159 struct mb_display *disp = mb_display_get(); 00160 00161 printk("button_send_pressed()\n"); 00162 if(OnOff_Value % 2) { 00163 mb_display_print(disp, MB_DISPLAY_MODE_SINGLE, 100000, 00164 "%s", groupAddress2String[groupAddress - GROUP_ADDR]); 00165 } 00166 else 00167 { 00168 mb_display_print(disp, MB_DISPLAY_MODE_SINGLE, 100000, 00169 "%s", " "); 00170 } 00171 genericOnOffSet(); 00172 } 00173 00174 /* button B callback, direct invoke by interrupt routine, need to be out of this callback ASAP. */ 00175 static void button_pressed(struct device *dev, struct gpio_callback *cb, 00176 uint32_t pins) 00177 { 00178 struct mb_display *disp = mb_display_get(); 00179 00180 /* 00181 * One button press within a 1 second interval sends an on message 00182 * More than one button press sends an off message 00183 */ 00184 time = k_uptime_get_32(); 00185 00186 /* debounce the switch */ 00187 if (time < last_time + BUTTON_DEBOUNCE_DELAY_MS) { 00188 last_time = time; 00189 return; 00190 } 00191 00192 if (pins & BIT(SW0_GPIO_PIN)) { 00193 k_work_submit(&button_work); 00194 } 00195 else { 00196 board_set_target(); 00197 00198 mb_display_print(disp, MB_DISPLAY_MODE_DEFAULT, SCROLL_SPEED, 00199 "%s", groupAddress2String[groupAddress - GROUP_ADDR]); 00200 } 00201 last_time = time; 00202 } 00203 00204 static const struct { 00205 char note; 00206 u32_t period; 00207 u32_t sharp; 00208 } period_map[] = { 00209 { 'C', 3822, 3608 }, 00210 { 'D', 3405, 3214 }, 00211 { 'E', 3034, 3034 }, 00212 { 'F', 2863, 2703 }, 00213 { 'G', 2551, 2407 }, 00214 { 'A', 2273, 2145 }, 00215 { 'B', 2025, 2025 }, 00216 }; 00217 00218 static u32_t get_period(char note, bool sharp) 00219 { 00220 int i; 00221 00222 if (note == ' ') { 00223 return 0; 00224 } 00225 00226 for (i = 0; i < ARRAY_SIZE(period_map); i++) { 00227 if (period_map[i].note != note) { 00228 continue; 00229 } 00230 00231 if (sharp) { 00232 return period_map[i].sharp; 00233 } else { 00234 return period_map[i].period; 00235 } 00236 } 00237 00238 return 1500; 00239 } 00240 00241 00242 void board_heartbeat(u8_t hops, u16_t feat) 00243 { 00244 struct mb_display *disp = mb_display_get(); 00245 const struct mb_image hops_img[] = { 00246 MB_IMAGE({ 1, 1, 1, 1, 1 }, 00247 { 1, 1, 1, 1, 1 }, 00248 { 1, 1, 1, 1, 1 }, 00249 { 1, 1, 1, 1, 1 }, 00250 { 1, 1, 1, 1, 1 }), 00251 MB_IMAGE({ 1, 1, 1, 1, 1 }, 00252 { 1, 1, 1, 1, 1 }, 00253 { 1, 1, 0, 1, 1 }, 00254 { 1, 1, 1, 1, 1 }, 00255 { 1, 1, 1, 1, 1 }), 00256 MB_IMAGE({ 1, 1, 1, 1, 1 }, 00257 { 1, 0, 0, 0, 1 }, 00258 { 1, 0, 0, 0, 1 }, 00259 { 1, 0, 0, 0, 1 }, 00260 { 1, 1, 1, 1, 1 }), 00261 MB_IMAGE({ 1, 1, 1, 1, 1 }, 00262 { 1, 0, 0, 0, 1 }, 00263 { 1, 0, 0, 0, 1 }, 00264 { 1, 0, 0, 0, 1 }, 00265 { 1, 1, 1, 1, 1 }), 00266 MB_IMAGE({ 1, 0, 1, 0, 1 }, 00267 { 0, 0, 0, 0, 0 }, 00268 { 1, 0, 0, 0, 1 }, 00269 { 0, 0, 0, 0, 0 }, 00270 { 1, 0, 1, 0, 1 }) 00271 }; 00272 00273 printk("%u hops\n", hops); 00274 00275 if (hops) { 00276 hops = min(hops, ARRAY_SIZE(hops_img)); 00277 mb_display_image(disp, MB_DISPLAY_MODE_SINGLE, K_SECONDS(2), 00278 &hops_img[hops - 1], 1); 00279 } 00280 } 00281 00282 void board_attention(bool attention) 00283 { 00284 struct mb_display *disp = mb_display_get(); 00285 static const struct mb_image attn_img[] = { 00286 MB_IMAGE({ 0, 0, 0, 0, 0 }, 00287 { 0, 0, 0, 0, 0 }, 00288 { 0, 0, 1, 0, 0 }, 00289 { 0, 0, 0, 0, 0 }, 00290 { 0, 0, 0, 0, 0 }), 00291 MB_IMAGE({ 0, 0, 0, 0, 0 }, 00292 { 0, 1, 1, 1, 0 }, 00293 { 0, 1, 1, 1, 0 }, 00294 { 0, 1, 1, 1, 0 }, 00295 { 0, 0, 0, 0, 0 }), 00296 MB_IMAGE({ 1, 1, 1, 1, 1 }, 00297 { 1, 1, 1, 1, 1 }, 00298 { 1, 1, 0, 1, 1 }, 00299 { 1, 1, 1, 1, 1 }, 00300 { 1, 1, 1, 1, 1 }), 00301 MB_IMAGE({ 1, 1, 1, 1, 1 }, 00302 { 1, 0, 0, 0, 1 }, 00303 { 1, 0, 0, 0, 1 }, 00304 { 1, 0, 0, 0, 1 }, 00305 { 1, 1, 1, 1, 1 }), 00306 }; 00307 00308 if (attention) { 00309 mb_display_image(disp, 00310 MB_DISPLAY_MODE_DEFAULT | MB_DISPLAY_FLAG_LOOP, 00311 K_MSEC(150), attn_img, ARRAY_SIZE(attn_img)); 00312 } else { 00313 mb_display_stop(disp); 00314 } 00315 } 00316 00317 static void configure_button(void) 00318 { 00319 static struct gpio_callback button_cb; 00320 00321 /* Initialize the button debouncer */ 00322 last_time = k_uptime_get_32(); 00323 00324 k_work_init(&button_work, button_send_pressed); 00325 00326 gpio = device_get_binding(SW0_GPIO_NAME); 00327 00328 gpio_pin_configure(gpio, SW0_GPIO_PIN, 00329 (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | 00330 GPIO_INT_ACTIVE_LOW)); 00331 gpio_pin_configure(gpio, SW1_GPIO_PIN, 00332 (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | 00333 GPIO_INT_ACTIVE_LOW)); 00334 00335 gpio_init_callback(&button_cb, button_pressed, 00336 BIT(SW0_GPIO_PIN) | BIT(SW1_GPIO_PIN)); 00337 gpio_add_callback(gpio, &button_cb); 00338 00339 gpio_pin_enable_callback(gpio, SW0_GPIO_PIN); 00340 gpio_pin_enable_callback(gpio, SW1_GPIO_PIN); 00341 } 00342 00343 void board_init(u16_t *addr) 00344 { 00345 struct mb_display *disp = mb_display_get(); 00346 00347 nvm = device_get_binding(FLASH_DEV_NAME); 00348 pwm = device_get_binding(CONFIG_PWM_NRF5_SW_0_DEV_NAME); 00349 00350 *addr = ( (u16_t)NRF_FICR->DEVICEADDR[0] ) & 0x7fff; 00351 printk("FICR 0x%02x\n", *addr); 00352 00353 mb_display_print(disp, MB_DISPLAY_MODE_DEFAULT, SCROLL_SPEED, 00354 "%s %s", "Client", groupAddress2String[groupAddress - GROUP_ADDR]); 00355 00356 configure_button(); 00357 } 00358 00359 static void heartbeat(u8_t hops, u16_t feat) 00360 { 00361 board_heartbeat(hops, feat); 00362 } 00363 00364 static struct bt_mesh_cfg_srv cfg_srv = { 00365 #if defined(CONFIG_BOARD_BBC_MICROBIT) 00366 .relay = BT_MESH_RELAY_ENABLED, 00367 .beacon = BT_MESH_BEACON_DISABLED, 00368 #else 00369 .relay = BT_MESH_RELAY_ENABLED, 00370 .beacon = BT_MESH_BEACON_ENABLED, 00371 #endif 00372 .frnd = BT_MESH_FRIEND_NOT_SUPPORTED, 00373 .default_ttl = 7, 00374 00375 /* 3 transmissions with 20ms interval */ 00376 .net_transmit = BT_MESH_TRANSMIT(2, 20), 00377 .relay_retransmit = BT_MESH_TRANSMIT(3, 20), 00378 00379 .hb_sub.func = heartbeat, 00380 }; 00381 00382 static struct bt_mesh_cfg_cli cfg_cli = { 00383 }; 00384 00385 00386 static void attention_on(struct bt_mesh_model *model) 00387 { 00388 printk("attention_on()\n"); 00389 board_attention(true); 00390 } 00391 00392 static void attention_off(struct bt_mesh_model *model) 00393 { 00394 printk("attention_off()\n"); 00395 board_attention(false); 00396 } 00397 00398 static const struct bt_mesh_health_srv_cb health_srv_cb = { 00399 .attn_on = attention_on, 00400 .attn_off = attention_off, 00401 }; 00402 00403 static struct bt_mesh_health_srv health_srv = { 00404 .cb = &health_srv_cb, 00405 }; 00406 00407 /* 00408 * OnOff Model Client Op Dispatch Table 00409 */ 00410 00411 static const struct bt_mesh_model_op gen_onoff_cli_op[] = { 00412 { BT_MESH_MODEL_OP_GEN_ONOFF_STATUS, 1, gen_onoff_status }, 00413 BT_MESH_MODEL_OP_END, 00414 }; 00415 00416 static struct bt_mesh_model root_models[] = { 00417 BT_MESH_MODEL_CFG_SRV(&cfg_srv), 00418 BT_MESH_MODEL_CFG_CLI(&cfg_cli), 00419 BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), 00420 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op, 00421 &gen_onoff_pub_cli, NULL), 00422 }; 00423 00424 static struct bt_mesh_elem elements[] = { 00425 BT_MESH_ELEM(0, root_models, /* vnd_models */ BT_MESH_MODEL_NONE), 00426 }; 00427 00428 static const struct bt_mesh_comp comp = { 00429 .cid = BT_COMP_ID_LF, 00430 .elem = elements, 00431 .elem_count = ARRAY_SIZE(elements), 00432 }; 00433 00434 /* 00435 * Generic OnOff Model Server Message Handlers 00436 * 00437 * Mesh Model Specification 3.1.1 00438 * 00439 */ 00440 00441 static void gen_onoff_get(struct bt_mesh_model *model, 00442 struct bt_mesh_msg_ctx *ctx, 00443 struct net_buf_simple *buf) 00444 { 00445 printk("gen_onoff_get...\n"); 00446 } 00447 00448 static void gen_onoff_set_unack(struct bt_mesh_model *model, 00449 struct bt_mesh_msg_ctx *ctx, 00450 struct net_buf_simple *buf) 00451 { 00452 printk("gen_onoff_set_unack...\n"); 00453 } 00454 00455 static void gen_onoff_set(struct bt_mesh_model *model, 00456 struct bt_mesh_msg_ctx *ctx, 00457 struct net_buf_simple *buf) 00458 { 00459 printk("gen_onoff_set...\n"); 00460 00461 } 00462 00463 static void gen_onoff_status(struct bt_mesh_model *model, 00464 struct bt_mesh_msg_ctx *ctx, 00465 struct net_buf_simple *buf) 00466 { 00467 printk("gen_onoff_status...\n"); 00468 } 00469 00470 static void configure(void) 00471 { 00472 int status; 00473 00474 printk("Configuring...\n"); 00475 00476 /* Add Application Key */ 00477 status = bt_mesh_cfg_app_key_add(net_idx, addr, net_idx, app_idx, app_key, NULL); 00478 printk("bt_mesh_cfg_app_key_add = %d \n", status); 00479 00480 00481 /* Bind to Generic on/off client model */ 00482 status = bt_mesh_cfg_mod_app_bind(net_idx, addr, addr, app_idx, 00483 BT_MESH_MODEL_ID_GEN_ONOFF_CLI, NULL); 00484 printk("bt_mesh_cfg_mod_app_bind = %d \n", status); 00485 00486 status = bt_mesh_cfg_mod_sub_add(net_idx, addr, addr, 00487 GROUP_ADDR, BT_MESH_MODEL_ID_GEN_ONOFF_CLI, NULL); 00488 printk("bt_mesh_cfg_mod_sub_add = %d \n", status); 00489 00490 00491 struct bt_mesh_cfg_hb_sub sub = { 00492 .src = PUBLISHER_ADDR, 00493 .dst = GROUP_ADDR, 00494 .period = 0x10, 00495 }; 00496 00497 bt_mesh_cfg_hb_sub_set(net_idx, addr, &sub, NULL); 00498 printk("Subscribing to heartbeat messages\n"); 00499 00500 00501 printk("Configuration complete\n"); 00502 00503 } 00504 00505 static const u8_t dev_uuid[16] = { 0xdd, 0xdd }; 00506 00507 static const struct bt_mesh_prov prov = { 00508 .uuid = dev_uuid, 00509 }; 00510 00511 static void bt_ready(int err) 00512 { 00513 if (err) { 00514 printk("Bluetooth init failed (err %d)\n", err); 00515 return; 00516 } 00517 00518 printk("Bluetooth initialized\n"); 00519 00520 err = bt_mesh_init(&prov, &comp); 00521 if (err) { 00522 printk("Initializing mesh failed (err %d)\n", err); 00523 return; 00524 } 00525 00526 printk("Mesh initialized\n"); 00527 00528 if (IS_ENABLED(CONFIG_BT_SETTINGS)) { 00529 printk("Loading stored settings\n"); 00530 settings_load(); 00531 } 00532 00533 err = bt_mesh_provision(net_key, net_idx, flags, iv_index, addr, 00534 dev_key); 00535 00536 if (err == -EALREADY) { 00537 printk("Using stored settings\n"); 00538 } else if (err) { 00539 printk("Provisioning failed (err %d)\n", err); 00540 return; 00541 } else { 00542 printk("Provisioning completed\n"); 00543 configure(); 00544 } 00545 00546 printk("Provisioning completed\n"); 00547 00548 configure(); 00549 } 00550 00551 static void genericOnOffSet(void) 00552 { 00553 NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4); 00554 struct bt_mesh_msg_ctx ctx = { 00555 .net_idx = net_idx, 00556 .app_idx = app_idx, 00557 .addr = groupAddress, 00558 .send_ttl = BT_MESH_TTL_DEFAULT, 00559 }; 00560 00561 /* Bind to Generic OnOff Model */ 00562 bt_mesh_model_msg_init(&msg, BT_MESH_MODEL_OP_GEN_ONOFF_SET ); 00563 00564 net_buf_simple_add_u8(&msg, OnOff_Value % 2); 00565 OnOff_Value++; 00566 net_buf_simple_add_u8(&msg, trans_ID++); 00567 00568 if (bt_mesh_model_send(&root_models[3], &ctx, &msg, NULL, NULL)) { 00569 printk("Unable to send Vendor Button message\n"); 00570 } 00571 00572 printk("Button message sent with addr 0x%04x\n", groupAddress); 00573 } 00574 00575 void main(void) 00576 { 00577 int err; 00578 00579 printk("Initializing...\n"); 00580 00581 board_init(&addr); 00582 00583 printk("Unicast address: 0x%04x, name: %s\n", addr, groupAddress2String[groupAddress - GROUP_ADDR]); 00584 00585 /* Initialize the Bluetooth Subsystem */ 00586 err = bt_enable(bt_ready); 00587 if (err) { 00588 printk("Bluetooth init failed (err %d)\n", err); 00589 } 00590 00591 while (1) { 00592 00593 } 00594 00595 }
Generated on Thu Jul 21 2022 12:10:50 by
