Kai Ren / client
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.c Source File

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 }