diff --git a/Cargo.lock b/Cargo.lock index 2ae7ad3..c25bfea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,25 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -41,6 +60,12 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +[[package]] +name = "bumpalo" +version = "3.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" + [[package]] name = "bytemuck" version = "1.25.0" @@ -67,7 +92,6 @@ checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" dependencies = [ "bare-metal", "bitfield", - "critical-section", "embedded-hal 0.2.7", "volatile-register", ] @@ -89,7 +113,7 @@ checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -104,14 +128,38 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core 0.13.4", + "darling_macro 0.13.4", +] + [[package]] name = "darling" version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", ] [[package]] @@ -124,8 +172,19 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", - "syn", + "strsim 0.11.1", + "syn 2.0.114", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core 0.13.4", + "quote", + "syn 1.0.109", ] [[package]] @@ -134,9 +193,18 @@ version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "darling_core", + "darling_core 0.20.11", "quote", - "syn", + "syn 2.0.114", +] + +[[package]] +name = "defmt" +version = "0.3.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0963443817029b2024136fc4dd07a5107eb8f977eaf18fcd1fdeb11306b64ad" +dependencies = [ + "defmt 1.0.1", ] [[package]] @@ -159,7 +227,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -178,7 +246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93d5a25c99d89c40f5676bec8cefe0614f17f0f40e916f98e345dae941807f9e" dependencies = [ "critical-section", - "defmt", + "defmt 1.0.1", ] [[package]] @@ -196,10 +264,10 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "554e3e840696f54b4c9afcf28a0f24da431c927f4151040020416e7393d6d0d8" dependencies = [ - "defmt", + "defmt 1.0.1", "embassy-futures", "embassy-hal-internal", - "embassy-sync", + "embassy-sync 0.7.2", "embassy-time", "embedded-hal 0.2.7", "embedded-hal 1.0.0", @@ -217,7 +285,7 @@ checksum = "06070468370195e0e86f241c8e5004356d696590a678d47d6676795b2e439c6b" dependencies = [ "cortex-m", "critical-section", - "defmt", + "defmt 1.0.1", "document-features", "embassy-executor-macros", "embassy-executor-timer-queue", @@ -229,10 +297,10 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfdddc3a04226828316bf31393b6903ee162238576b1584ee2669af215d55472" dependencies = [ - "darling", + "darling 0.20.11", "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -247,7 +315,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01" dependencies = [ - "defmt", + "defmt 1.0.1", ] [[package]] @@ -258,7 +326,7 @@ checksum = "95285007a91b619dc9f26ea8f55452aa6c60f7115a4edc05085cd2bd3127cd7a" dependencies = [ "cortex-m", "critical-section", - "defmt", + "defmt 1.0.1", "num-traits", ] @@ -273,11 +341,11 @@ dependencies = [ "cortex-m", "cortex-m-rt", "critical-section", - "defmt", + "defmt 1.0.1", "document-features", "embassy-embedded-hal", "embassy-hal-internal", - "embassy-sync", + "embassy-sync 0.7.2", "embassy-time", "embassy-time-driver", "embassy-time-queue-utils", @@ -295,6 +363,19 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "embassy-sync" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd938f25c0798db4280fcd8026bf4c2f48789aebf8f77b6e5cf8a7693ba114ec" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async", + "futures-util", + "heapless", +] + [[package]] name = "embassy-sync" version = "0.7.2" @@ -303,7 +384,7 @@ checksum = "73974a3edbd0bd286759b3d483540f0ebef705919a5f56f4fc7709066f71689b" dependencies = [ "cfg-if", "critical-section", - "defmt", + "defmt 1.0.1", "embedded-io-async", "futures-core", "futures-sink", @@ -318,7 +399,7 @@ checksum = "f4fa65b9284d974dad7a23bb72835c4ec85c0b540d86af7fc4098c88cff51d65" dependencies = [ "cfg-if", "critical-section", - "defmt", + "defmt 1.0.1", "document-features", "embassy-time-driver", "embedded-hal 0.2.7", @@ -352,7 +433,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17119855ccc2d1f7470a39756b12068454ae27a3eabb037d940b5c03d9c77b7a" dependencies = [ - "defmt", + "defmt 1.0.1", "embedded-io-async", ] @@ -429,18 +510,67 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + [[package]] name = "futures-sink" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "half" version = "2.7.1" @@ -477,12 +607,34 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "js-sys" +version = "0.3.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "litrs" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + [[package]] name = "nb" version = "0.1.3" @@ -508,6 +660,60 @@ dependencies = [ "cortex-m-rt", ] +[[package]] +name = "nrf-softdevice" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225a21d963b2382617dbbff5953dc8c6c43fe56db5c5155f4d20a30c50c2766d" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "critical-section", + "defmt 0.3.100", + "embassy-futures", + "embassy-sync 0.5.0", + "embedded-storage", + "embedded-storage-async", + "fixed", + "futures", + "heapless", + "nrf-softdevice-macro", + "nrf-softdevice-s140", + "nrf52840-pac", + "num_enum", +] + +[[package]] +name = "nrf-softdevice-macro" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3af0752f2f12e202fa29f5a8d2f6dcc8a421c7a7e368d9dab7feb6bfe24ff0e9" +dependencies = [ + "Inflector", + "darling 0.13.4", + "proc-macro2", + "quote", + "syn 1.0.109", + "uuid", +] + +[[package]] +name = "nrf-softdevice-s140" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea93a1e11efdafcf914ed6b81b5be0cd99ee8ff6c3060102265ea863a355393" + +[[package]] +name = "nrf52840-pac" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30713f36f1be02e5bc9abefa30eae4a1f943d810f199d4923d3ad062d1be1b3d" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "vcell", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -517,23 +723,51 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_enum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "odesa" version = "0.1.0" dependencies = [ "cortex-m", "cortex-m-rt", - "defmt", + "defmt 1.0.1", "defmt-rtt", "embassy-executor", "embassy-futures", "embassy-nrf", - "embassy-sync", + "embassy-sync 0.7.2", "embassy-time", + "nrf-softdevice", "panic-halt", "panic-probe", ] +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + [[package]] name = "panic-halt" version = "1.0.0" @@ -547,9 +781,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd402d00b0fb94c5aee000029204a46884b1262e0c443f166d86d2c0747e1a1a" dependencies = [ "cortex-m", - "defmt", + "defmt 1.0.1", ] +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "proc-macro-error-attr2" version = "2.0.0" @@ -569,7 +815,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -602,6 +848,35 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" + [[package]] name = "rustc_version" version = "0.2.3" @@ -611,6 +886,12 @@ dependencies = [ "semver", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "semver" version = "0.9.0" @@ -632,12 +913,29 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.114" @@ -666,7 +964,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -681,6 +979,16 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +[[package]] +name = "uuid" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "vcell" version = "0.1.3" @@ -702,6 +1010,51 @@ dependencies = [ "vcell", ] +[[package]] +name = "wasm-bindgen" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.114", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +dependencies = [ + "unicode-ident", +] + [[package]] name = "zerocopy" version = "0.8.39" @@ -719,5 +1072,5 @@ checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] diff --git a/Cargo.toml b/Cargo.toml index 0fe77b5..fff6d74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ name = "odesa" version = "0.1.0" [dependencies] -cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } +cortex-m = { version = "0.7.7", features = ["inline-asm"] } cortex-m-rt = "0.7.5" defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.1.0", optional = true } @@ -17,7 +17,7 @@ embassy-sync = { version = "0.7.2", features = ["defmt"] } embassy-time = { version = "0.5.0", features = ["tick-hz-32_768", "defmt", "defmt-timestamp-uptime"] } panic-halt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"], optional = true } -#nrf-softdevice = { version = "0.1.0", features = ["s140", "ble-peripheral", "nrf52840"] } +nrf-softdevice = { version = "0.1.0", features = ["s140", "ble-peripheral", "nrf52840", "nrf-softdevice-s140", "critical-section-impl", "defmt", "nrf52840-pac", "critical-section", "ble-gatt-server"] } [[bin]] name = "odesa" @@ -26,13 +26,13 @@ bench = false [profile.dev] debug = true -lto = true +lto = false opt-level = "z" incremental = true [profile.release] debug = false -lto = true +lto = false opt-level = "z" incremental = true diff --git a/src/main.rs b/src/main.rs index bf98d0a..951c930 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,14 +15,17 @@ use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::{join3, join4}; -use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pull}; +use embassy_nrf::gpio::{AnyPin, Input, OutputDrive, Pull}; +use embassy_nrf::interrupt::Priority; use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; use embassy_nrf::Peri; use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::mutex::Mutex; use embassy_sync::signal::Signal; use embassy_time::{with_timeout, Duration, Timer}; -// use nrf_softdevice::{raw, Softdevice}; +use nrf_softdevice::{raw, Softdevice}; +use nrf_softdevice::ble::advertisement_builder::{Flag, LegacyAdvertisementBuilder, LegacyAdvertisementPayload, ServiceList, ServiceUuid16}; +use nrf_softdevice::ble::{peripheral, gatt_server}; #[derive(Copy, Clone, Eq, PartialEq, Format)] enum SysAction { @@ -61,51 +64,196 @@ static SYS_ACTION: Mutex = Mutex::new(SysAction:: static TEXT_ANIMATION: Mutex = Mutex::new(TextLightType::Hue); static HEART_ANIMATION: Mutex = Mutex::new(HeartLightType::HeartBeat); +#[nrf_softdevice::gatt_service(uuid = "9e7312e0-2354-11eb-9f10-fbc30a62cf38")] +struct AnimationService { + #[characteristic(uuid = "9e7312e0-2354-11eb-9f10-fbc30a63cf38", read, write, notify, indicate)] + text_mode: u16, + #[characteristic(uuid = "9e7312e0-2354-11eb-9f10-fbc30a64cf38", read, write, notify, indicate)] + text_color: u16, + #[characteristic(uuid = "9e7312e0-2354-11eb-9f10-fbc30a65cf38", read, write, notify, indicate)] + heart_mode: u16, + #[characteristic(uuid = "9e7312e0-2354-11eb-9f10-fbc30a66cf38", read, write, notify, indicate)] + heart_color: u16, + +} + +#[nrf_softdevice::gatt_service(uuid = "180f")] +struct BatteryService { + #[characteristic(uuid = "2a19", read, notify)] + battery_level: u8, +} + +#[nrf_softdevice::gatt_server] +struct Server { + bas: BatteryService, + light: AnimationService, +} + #[embassy_executor::main] async fn main(spawner: Spawner) { - // let config = nrf_softdevice::Config { - // clock: Some(raw::nrf_clock_lf_cfg_t { - // source: raw::NRF_CLOCK_LF_SRC_RC as u8, - // rc_ctiv: 16, - // rc_temp_ctiv: 2, - // accuracy: raw::NRF_CLOCK_LF_ACCURACY_500_PPM as u8, - // }), - // conn_gap: Some(raw::ble_gap_conn_cfg_t { - // conn_count: 6, - // event_length: 24, - // }), - // conn_gatt: Some(raw::ble_gatt_conn_cfg_t { att_mtu: 256 }), - // gatts_attr_tab_size: Some(raw::ble_gatts_cfg_attr_tab_size_t { - // attr_tab_size: raw::BLE_GATTS_ATTR_TAB_SIZE_DEFAULT, - // }), - // gap_role_count: Some(raw::ble_gap_cfg_role_count_t { - // adv_set_count: 1, - // periph_role_count: 3, - // central_role_count: 3, - // central_sec_count: 0, - // _bitfield_1: raw::ble_gap_cfg_role_count_t::new_bitfield_1(0), - // }), - // gap_device_name: Some(raw::ble_gap_cfg_device_name_t { - // p_value: b"HelloRust" as *const u8 as _, - // current_len: 9, - // max_len: 9, - // write_perm: unsafe { mem::zeroed() }, - // _bitfield_1: raw::ble_gap_cfg_device_name_t::new_bitfield_1(raw::BLE_GATTS_VLOC_STACK as u8), - // }), - // ..Default::default() - // }; - // - // let _sd = Softdevice::enable(&config); + let mut config = embassy_nrf::config::Config::default(); + config.gpiote_interrupt_priority = Priority::P2; + config.time_interrupt_priority = Priority::P2; + let p = embassy_nrf::init(config); + + let config = nrf_softdevice::Config { + clock: Some(raw::nrf_clock_lf_cfg_t { + source: raw::NRF_CLOCK_LF_SRC_RC as u8, + rc_ctiv: 16, + rc_temp_ctiv: 2, + accuracy: raw::NRF_CLOCK_LF_ACCURACY_500_PPM as u8, + }), + conn_gap: Some(raw::ble_gap_conn_cfg_t { + conn_count: 6, + event_length: 24, + }), + conn_gatt: Some(raw::ble_gatt_conn_cfg_t { att_mtu: 256 }), + gatts_attr_tab_size: Some(raw::ble_gatts_cfg_attr_tab_size_t { + attr_tab_size: raw::BLE_GATTS_ATTR_TAB_SIZE_DEFAULT, + }), + gap_role_count: Some(raw::ble_gap_cfg_role_count_t { + adv_set_count: 1, + periph_role_count: 3, + central_role_count: 3, + central_sec_count: 0, + _bitfield_1: raw::ble_gap_cfg_role_count_t::new_bitfield_1(0), + }), + gap_device_name: Some(raw::ble_gap_cfg_device_name_t { + p_value: b"Odesa!" as *const u8 as _, + current_len: 9, + max_len: 9, + write_perm: unsafe { mem::zeroed() }, + _bitfield_1: raw::ble_gap_cfg_device_name_t::new_bitfield_1(raw::BLE_GATTS_VLOC_STACK as u8), + }), + ..Default::default() + }; + + let sd = Softdevice::enable(&config); + let server = Server::new(sd).expect("failed to enable softdevice"); - let p = embassy_nrf::init(Default::default()); let pwm_text = SimplePwm::new_3ch(p.PWM0, p.P1_15, p.P1_13, p.P1_11, &Default::default()); let pwm_heart = SimplePwm::new_3ch(p.PWM2, p.P0_31, p.P0_29, p.P0_02, &Default::default()); spawner.spawn(radar_task()).expect("failed to spawn radar task"); + spawner.spawn(touch_button(p.P0_20.into())).expect("failed to spawn touch task"); spawner.spawn(actions_task()).expect("failed to spawn actions task"); + spawner.spawn(softdevice_task(sd)).expect("failed to spawn softdevice task"); - join4(touch_button(p.P0_20.into()), moving_radar(p.P0_22.into()), heartbeat_task(pwm_heart), light_task(pwm_text)).await; + join4(gatt_task(server, sd), moving_radar(p.P0_22.into()), heartbeat_task(pwm_heart), light_task(pwm_text)).await; } +async fn gatt_task(server: Server, sd: &'static Softdevice) { + static ADV_DATA: LegacyAdvertisementPayload = LegacyAdvertisementBuilder::new() + .flags(&[Flag::GeneralDiscovery, Flag::LE_Only]) + .services_16(ServiceList::Complete, &[ServiceUuid16::BATTERY]) + .full_name("Odesa!") + .build(); + + static SCAN_DATA: LegacyAdvertisementPayload = LegacyAdvertisementBuilder::new() + .services_128( + ServiceList::Complete, + &[0x9e7312e0_2354_11eb_9f10_fbc30a62cf38_u128.to_le_bytes()], + ) + .build(); + + loop { + let config = peripheral::Config::default(); + let adv = peripheral::ConnectableAdvertisement::ScannableUndirected { + adv_data: &ADV_DATA, + scan_data: &SCAN_DATA, + }; + let conn = peripheral::advertise_connectable(sd, adv, &config).await.expect("failed to advertise"); + + info!("advertising done!"); + + // Run the GATT server on the connection. This returns when the connection gets disconnected. + // + // Event enums (ServerEvent's) are generated by nrf_softdevice::gatt_server + // proc macro when applied to the Server struct above + let e = gatt_server::run(&conn, &server, |e| match e { + ServerEvent::Bas(e) => match e { + BatteryServiceEvent::BatteryLevelCccdWrite { notifications } => { + info!("battery notifications: {}", notifications) + } + }, + ServerEvent::Light(e) => match e { + AnimationServiceEvent::TextModeWrite(val) => { + let val = val % 3; + info!("wrote text mode: {}", val); + if let Err(e) = server.light.text_mode_notify(&conn, &(val)) { + info!("send notification error: {:?}", e); + } + let next = match val { + 0 => TextLightType::Hue, + 1 => TextLightType::ConstantColor, + 2 => TextLightType::White, + _ => TextLightType::Hue, + }; + TEXT_ANIMATION_SIGNAL.signal(next); + } + AnimationServiceEvent::TextColorWrite(val) => { + info!("wrote text color: {}", val); + if let Err(e) = server.light.text_color_notify(&conn, &(val)) { + info!("send notification error: {:?}", e); + } + } + AnimationServiceEvent::HeartModeWrite(val) => { + let val = val % 3; + info!("wrote heart mode: {}", val); + if let Err(e) = server.light.heart_mode_notify(&conn, &(val)) { + info!("send notification error: {:?}", e); + } + let next = match val { + 0 => HeartLightType::HeartBeat, + 1 => HeartLightType::Hue, + 2 => HeartLightType::ConstantColor, + _ => HeartLightType::HeartBeat, + }; + HEART_ANIMATION_SIGNAL.signal(next); + } + AnimationServiceEvent::HeartColorWrite(val) => { + info!("wrote heart color: {}", val); + if let Err(e) = server.light.heart_color_notify(&conn, &(val)) { + info!("send notification error: {:?}", e); + } + } + AnimationServiceEvent::TextModeCccdWrite { + indications, + notifications, + } => { + info!("text mode indications: {}, notifications: {}", indications, notifications) + } + AnimationServiceEvent::TextColorCccdWrite { + indications, + notifications, + } => { + info!("text color indications: {}, notifications: {}", indications, notifications) + } + AnimationServiceEvent::HeartModeCccdWrite { + indications, + notifications, + } => { + info!("text mode indications: {}, notifications: {}", indications, notifications) + } + AnimationServiceEvent::HeartColorCccdWrite { + indications, + notifications, + } => { + info!("text color indications: {}, notifications: {}", indications, notifications) + } + }, + }) + .await; + + info!("gatt_server run exited with error: {:?}", e); + } +} + +#[embassy_executor::task] +async fn softdevice_task(sd: &'static Softdevice) -> ! { + sd.run().await +} + +#[embassy_executor::task] async fn touch_button(pin: Peri<'static, AnyPin>) { let mut button = Input::new(pin, Pull::Down); @@ -368,7 +516,6 @@ fn hue_to_rgb(hue: u16, max: u16) -> (u16, u16, u16) { async fn heartbeat_task(mut pwm: SimplePwm<'static>) { const MAX: u16 = 16384; - const MIN: u16 = 2048; pwm.set_max_duty(MAX); pwm.set_prescaler(Prescaler::Div1);