Remove old files

This commit is contained in:
marcelbuesing 2018-05-16 21:16:28 +02:00
parent c858e4de91
commit e17260a5fc
No known key found for this signature in database
GPG key ID: 03F06F8179D5549D
7 changed files with 846 additions and 1789 deletions

368
Cargo.lock generated
View file

@ -1,47 +1,3 @@
[[package]]
name = "aho-corasick"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bindgen"
version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clang-sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"which 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.0.1" version = "1.0.1"
@ -51,11 +7,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "bme680-rs" name = "bme680-rs"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bindgen 0.35.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"embedded-hal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "embedded-hal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -63,48 +17,6 @@ name = "byteorder"
version = "1.2.2" version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cc"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cexpr"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cfg-if"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clang-sys"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
"libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clap"
version = "2.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "embedded-hal" name = "embedded-hal"
version = "0.1.2" version = "0.1.2"
@ -113,293 +25,13 @@ dependencies = [
"nb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "nb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "env_logger"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gcc"
version = "0.3.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "glob"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "humantime"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libloading"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memchr"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memchr"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "nb" name = "nb"
version = "0.1.1" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "nom"
version = "3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quick-error"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quote"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_syscall"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_termios"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "strsim"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "termcolor"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termion"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ucd-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-width"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unreachable"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "utf8-ranges"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "which"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wincolor"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata] [metadata]
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4"
"checksum bindgen 0.35.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b023955126e7909ab9fc1d1973965b8b004f1f388afb5c589640ab483b3b0ad2"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87"
"checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc"
"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum clang-sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "939a1a34310b120d26eba35c29475933128b0ec58e24b43327f8dbe6036fc538"
"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
"checksum embedded-hal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "684b1fa3196f78342296d04edc2a6e5d053729d1b64a819dcb072810d706e267" "checksum embedded-hal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "684b1fa3196f78342296d04edc2a6e5d053729d1b64a819dcb072810d706e267"
"checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b"
"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2"
"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
"checksum nb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "69f380b5fe9fab8c0d7a6a99cda23e2cc0463bedb2cbc3aada0813b98496ecdc" "checksum nb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "69f380b5fe9fab8c0d7a6a99cda23e2cc0463bedb2cbc3aada0813b98496ecdc"
"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b"
"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb"
"checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756"
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum which 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e84a603e7e0b1ce1aa1ee2b109c7be00155ce52df5081590d1ffb93f4f515cb2"
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767"

View file

@ -1,14 +1,9 @@
[package] [package]
name = "bme680-rs" name = "bme680-rs"
version = "0.1.0" version = "0.1.0"
build = "build.rs"
authors = ["marcelbuesing <buesing.marcel@googlemail.com>"] authors = ["marcelbuesing <buesing.marcel@googlemail.com>"]
[dependencies] [dependencies]
bitflags = "1.0"
byteorder = "1.2" byteorder = "1.2"
embedded-hal = "0.1" embedded-hal = "0.1"
[build-dependencies]
bindgen = "0.35"
bitflags = "1.0"
gcc = "0.3"

View file

@ -1,34 +0,0 @@
extern crate bindgen;
extern crate gcc;
use std::env;
use std::path::PathBuf;
fn main() {
// Tell cargo to tell rustc to link the system bzip2
// shared library.
//println!("cargo:rustc-link-lib=bz2");
// gcc::Config::new()
// .file("BME680_driver/bme680.c")
// .include("BME680_driver")
// .compile("bme680.a");
//
// // The bindgen::Builder is the main entry point
// // to bindgen, and lets you build up options for
// // the resulting bindings.
// let bindings = bindgen::Builder::default()
// // The input header we would like to generate
// // bindings for.
// .header("wrapper.h")
// // Finish the builder and generate the bindings.
// .generate()
// // Unwrap the Result and panic on failure.
// .expect("Unable to generate bindings");
//
// // Write the bindings to the $OUT_DIR/bindings.rs file.
// let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
// bindings
// .write_to_file(out_path.join("bindings.rs"))
// .expect("Couldn't write bindings!");
}

View file

@ -1,907 +0,0 @@
use hal::blocking::delay::DelayMs;
use hal::blocking::i2c::{Read, Write};
use std::convert::TryFrom;
use std::result;
/** BME680 General config */
pub const BME680_POLL_PERIOD_MS: u8 = 10;
/** BME680 I2C addresses */
pub const BME680_I2C_ADDR_PRIMARY: u8 = 0x76;
pub const BME680_I2C_ADDR_SECONDARY: u8 = 0x77;
/** BME680 unique chip identifier */
pub const BME680_CHIP_ID: u8 = 0x61;
/** BME680 coefficients related defines */
pub const BME680_COEFF_SIZE: usize = 41;
pub const BME680_COEFF_ADDR1_LEN: u8 = 25;
pub const BME680_COEFF_ADDR2_LEN: u8 = 16;
/** BME680 field_x related defines */
pub const BME680_FIELD_LENGTH: u8 = 15;
pub const BME680_FIELD_ADDR_OFFSET: u8 = 17;
pub const BME680_SOFT_RESET_CMD: u8 = 0xb6;
pub const BME680_OK: i8 = 0;
/** Errors **/
pub const BME680_E_NULL_PTR: i8 = -1;
pub const BME680_E_COM_FAIL: i8 = -2;
pub const BME680_E_DEV_NOT_FOUND: i8 = -3;
pub const BME680_E_INVALID_LENGTH: i8 = -4;
/** Register map */
/** Other coefficient's address */
pub const BME680_ADDR_RES_HEAT_VAL_ADDR: u8 = 0x00;
pub const BME680_ADDR_RES_HEAT_RANGE_ADDR: u8 = 0x02;
pub const BME680_ADDR_RANGE_SW_ERR_ADDR: u8 = 0x04;
pub const BME680_ADDR_SENS_CONF_START: u8 = 0x5A;
pub const BME680_ADDR_GAS_CONF_START: u8 = 0x64;
pub const BME680_SOFT_RESET_ADDR: u8 = 0xe0;
/** Field settings */
pub const BME680_FIELD0_ADDR: u8 = 0x1d;
/** Heater settings */
pub const BME680_RES_HEAT0_ADDR: u8 = 0x5a;
pub const BME680_GAS_WAIT0_ADDR: u8 = 0x64;
/** Sensor configuration registers */
pub const BME680_CONF_HEAT_CTRL_ADDR: u8 = 0x70;
pub const BME680_CONF_ODR_RUN_GAS_NBC_ADDR: u8 = 0x71;
pub const BME680_CONF_OS_H_ADDR: u8 = 0x72;
pub const BME680_MEM_PAGE_ADDR: u8 = 0xf3;
pub const BME680_CONF_T_P_MODE_ADDR: u8 = 0x74;
pub const BME680_CONF_ODR_FILT_ADDR: u8 = 0x75;
/** Coefficient's address */
pub const BME680_COEFF_ADDR1: u8 = 0x89;
pub const BME680_COEFF_ADDR2: u8 = 0xe1;
/** Chip identifier */
pub const BME680_CHIP_ID_ADDR: u8 = 0xd0;
pub const BME680_SLEEP_MODE: u8 = 0;
pub const BME680_FORCED_MODE: u8 = 1;
pub const BME680_RESET_PERIOD: u8 = 10;
pub const BME680_GAS_MEAS_MSK: u8 = 0x30;
pub const BME680_NBCONV_MSK: u8 = 0x0F;
pub const BME680_FILTER_MSK: u8 = 0x1C;
pub const BME680_OST_MSK: u8 = 0xE0;
pub const BME680_OSP_MSK: u8 = 0x1C;
pub const BME680_OSH_MSK: u8 = 0x07;
pub const BME680_HCTRL_MSK: u8 = 0x08;
pub const BME680_RUN_GAS_MSK: u8 = 0x10;
pub const BME680_MODE_MSK: u8 = 0x03;
pub const BME680_RHRANGE_MSK: u8 = 0x30;
pub const BME680_RSERROR_MSK: u8 = 0xf0;
pub const BME680_NEW_DATA_MSK: u8 = 0x80;
pub const BME680_GAS_INDEX_MSK: u8 = 0x0f;
pub const BME680_GAS_RANGE_MSK: u8 = 0x0f;
pub const BME680_GASM_VALID_MSK: u8 = 0x20;
pub const BME680_HEAT_STAB_MSK: u8 = 0x10;
pub const BME680_MEM_PAGE_MSK: u8 = 0x10;
pub const BME680_SPI_RD_MSK: u8 = 0x80;
pub const BME680_SPI_WR_MSK: u8 = 0x7f;
pub const BME680_BIT_H1_DATA_MSK: u8 = 0x0F;
///
/// SPI memory page settings
///
pub const BME680_MEM_PAGE0: u8 = 0x10;
///
/// SPI memory page settings
///
pub const BME680_MEM_PAGE1: u8 = 0x00;
/** Buffer length macro declaration */
pub const BME680_TMP_BUFFER_LENGTH: usize = 40;
pub const BME680_REG_BUFFER_LENGTH: usize = 6;
pub const BME680_FIELD_DATA_LENGTH: usize = 3;
pub const BME680_GAS_REG_BUF_LENGTH: usize = 20;
/* Settings selector */
pub const BME680_OST_SEL: u16 = 1;
pub const BME680_OSP_SEL: u16 = 2;
pub const BME680_OSH_SEL: u16 = 4;
pub const BME680_GAS_MEAS_SEL: u16 = 8;
pub const BME680_FILTER_SEL: u16 = 16;
pub const BME680_HCNTRL_SEL: u16 = 32;
pub const BME680_RUN_GAS_SEL: u16 = 64;
pub const BME680_NBCONV_SEL: u16 = 128;
pub const BME680_GAS_SENSOR_SEL: u16 = BME680_GAS_MEAS_SEL | BME680_RUN_GAS_SEL | BME680_NBCONV_SEL;
pub enum Bme680Error {
///
/// aka BME680_E_NULL_PTR
///
NulltPtr,
///
/// aka BME680_E_COM_FAIL
///
CommunicationFailure,
///
/// aka BME680_E_DEV_NOT_FOUND
///
DeviceNotFound,
///
/// aka BME680_E_INVALID_LENGTH
///
InvalidLength,
///
/// Warning aka BME680_W_DEFINE_PWR_MODE
///
DefinePwrMode,
///
/// Warning aka BME680_W_DEFINE_PWR_MODE
///
NoNewData,
///
/// Warning Boundary Check
///
BoundaryCheckFailure(InfoMsg, u8, u8),
}
pub type Result<T> = result::Result<T, Bme680Error>;
///
/// Power mode settings
///
#[derive(PartialEq, Clone, Copy)]
pub enum PowerMode {
SleepMode,
ForcedMode,
}
impl PowerMode {
fn from(power_mode: u8) -> Self {
match power_mode {
BME680_SLEEP_MODE => PowerMode::SleepMode,
BME680_FORCED_MODE => PowerMode::ForcedMode,
_ => panic!("Unknown power mode: {}", power_mode),
}
}
fn value(&self) -> u8 {
match self {
PowerMode::SleepMode => BME680_SLEEP_MODE,
PowerMode::ForcedMode => BME680_FORCED_MODE,
}
}
}
#[derive(Clone, Copy)]
#[repr(i32)]
pub enum Bme680_intf {
BME680_SPI_INTF,
BME680_I2C_INTF,
}
#[derive(Default, Copy)]
#[repr(C)]
pub struct CalibData {
pub par_h1: u16,
pub par_h2: u16,
pub par_h3: i8,
pub par_h4: i8,
pub par_h5: i8,
pub par_h6: u8,
pub par_h7: i8,
pub par_gh1: i8,
pub par_gh2: i16,
pub par_gh3: i8,
pub par_t1: u16,
pub par_t2: i16,
pub par_t3: i8,
pub par_p1: u16,
pub par_p2: i16,
pub par_p3: i8,
pub par_p4: i16,
pub par_p5: i16,
pub par_p6: i8,
pub par_p7: i8,
pub par_p8: i16,
pub par_p9: i16,
pub par_p10: u8,
pub t_fine: i32,
pub res_heat_range: u8,
pub res_heat_val: i8,
pub range_sw_err: u8,
}
impl Clone for CalibData {
fn clone(&self) -> Self {
*self
}
}
#[derive(Default, Copy)]
#[repr(C)]
pub struct TphSett {
pub os_hum: Option<u8>,
pub os_temp: Option<u8>,
pub os_pres: Option<u8>,
pub filter: Option<u8>,
}
impl Clone for TphSett {
fn clone(&self) -> Self {
*self
}
}
#[derive(Default, Copy)]
#[repr(C)]
pub struct GasSett {
pub nb_conv: Option<u8>,
pub heatr_ctrl: Option<u8>,
pub run_gas: Option<u8>,
pub heatr_temp: Option<u16>,
pub heatr_dur: Option<u16>,
}
impl Clone for GasSett {
fn clone(&self) -> Self {
*self
}
}
#[derive(Default, Copy)]
#[repr(C)]
pub struct FieldData {
pub status: u8,
pub gas_index: u8,
pub meas_index: u8,
pub temperature: i16,
pub pressure: u32,
pub humidity: u32,
pub gas_resistance: u32,
}
impl Clone for FieldData {
fn clone(&self) -> Self {
*self
}
}
/// TODO - replace naming of "State" with something better
/// aka new_fields - BME680_NEW_DATA_MSK
///
pub enum FieldDataState {
NewData,
// TODO find better naming to no new data
NoNewData,
}
/// Infos
bitflags! {
#[derive(Default)]
pub struct InfoMsg: u8 {
const MIN_CORRECTION = 1;
const MAX_CORRECTION = 2;
}
}
#[derive(Default)]
pub struct SensorSettings {
gas_sett: GasSett,
tph_sett: TphSett,
}
bitflags! {
pub struct DesiredSensorSettings: u16 {
/// To set temperature oversampling
const OST_SEL = 1;
/// To set pressure oversampling.
const OSP_SEL = 2;
/// To set humidity oversampling.
const OSH_SEL = 4;
/// To set gas measurement setting.
const GAS_MEAS_SEL = 8;
/// To set filter setting.
const FILTER_SEL = 16;
/// To set humidity control setting.
const HCNTRL_SEL = 32;
/// To set run gas setting.
const RUN_GAS_SEL = 64;
/// To set NB conversion setting.
const NBCONV_SEL = 128;
/// To set all gas sensor related settings
const GAS_SENSOR_SEL = Self::GAS_MEAS_SEL.bits | Self::RUN_GAS_SEL.bits | Self::NBCONV_SEL.bits;
}
}
#[repr(C)]
pub struct Bme680_dev<I2C, D> {
pub i2c: I2C,
pub delay: D,
pub dev_id: u8,
pub mem_page: u8,
pub amb_temp: i8,
pub calib: CalibData,
pub tph_sett: TphSett,
pub gas_sett: GasSett,
pub power_mode: PowerMode,
pub new_fields: u8,
pub info_msg: u8,
}
fn boundary_check(value: Option<u8>, min: u8, max: u8) -> Result<u8> {
let mut info_msg: InfoMsg = Default::default();
// TODO give the nullptr here a different name
let value = value.ok_or(Bme680Error::NulltPtr)?;
if value < min {
info_msg |= InfoMsg::MIN_CORRECTION;
}
if value > max {
info_msg |= InfoMsg::MAX_CORRECTION;
}
if info_msg.is_empty() {
return Err(Bme680Error::BoundaryCheckFailure(info_msg, min, max));
}
Ok(value)
}
impl<I2C, D> Bme680_dev<I2C, D>
where
D: DelayMs<u8>,
I2C: Read + Write,
{
pub fn init(&mut self) -> Result<()> {
self.soft_reset()?;
/* Soft reset to restore it to default values*/
let chip_id = self.get_regs_u8(BME680_CHIP_ID_ADDR)?;
if chip_id == BME680_CHIP_ID {
self.calib = self.get_calib_data()?;
Ok(())
} else {
Err(Bme680Error::DeviceNotFound)
}
}
pub fn get_regs_u8(&mut self, reg_addr: u8) -> Result<u8> {
let mut buf = [0; 1];
match self.i2c.read(reg_addr, &mut buf) {
Ok(()) => Ok(buf[0]),
Err(_) => Err(Bme680Error::CommunicationFailure),
}
}
pub fn get_regs_i8(&mut self, reg_addr: u8) -> Result<i8> {
let mut buf = [0; 1];
match self.i2c.read(reg_addr, &mut buf) {
Ok(()) => Ok(i8::try_from(buf[0]).expect("U8 overflow when reading register")),
Err(_) => Err(Bme680Error::CommunicationFailure),
}
}
pub fn bme680_set_regs(&mut self, reg: &[(u8, u8)]) -> Result<()> {
if reg.is_empty() || reg.len() > (BME680_TMP_BUFFER_LENGTH / 2) as usize {
return Err(Bme680Error::InvalidLength);
}
let mut tmp_buff = Vec::with_capacity(BME680_TMP_BUFFER_LENGTH);
for (reg_addr, reg_data) in reg {
tmp_buff.push(reg_addr.to_owned());
tmp_buff.push(reg_data.to_owned());
}
self.i2c
.write(self.dev_id, tmp_buff.as_slice())
.map_err(|_| Bme680Error::CommunicationFailure)
}
pub fn soft_reset(&mut self) -> Result<()> {
self.bme680_set_regs(&[(BME680_SOFT_RESET_ADDR, BME680_SOFT_RESET_CMD)])?;
self.delay.delay_ms(BME680_RESET_PERIOD);
Ok(())
}
// TODO replace parameter desired_settings with safe flags
pub fn bme680_set_sensor_settings(
&mut self,
desired_settings: DesiredSensorSettings,
gas_sett: Option<GasSett>,
) -> Result<()> {
let mut reg_addr: u8;
let mut reg = Vec::with_capacity(BME680_REG_BUFFER_LENGTH);
let intended_power_mode = self.power_mode;
if desired_settings.contains(DesiredSensorSettings::GAS_MEAS_SEL) {
self.set_gas_config(gas_sett.unwrap())?;
}
let power_mode = self.power_mode;
self.bme680_set_sensor_mode(power_mode)?;
/* Selecting the filter */
if desired_settings.contains(DesiredSensorSettings::FILTER_SEL) {
let tph_sett_filter = boundary_check(self.tph_sett.filter, 0, 7)?;
reg_addr = 0x75u8;
let mut data = self.get_regs_u8(reg_addr)?;
// TODO duplicate check of condition ?
if desired_settings.contains(DesiredSensorSettings::FILTER_SEL) {
data = (data as (i32) & !0x1ci32 |tph_sett_filter as (i32) << 2i32 & 0x1ci32)
as (u8);
}
reg.push((reg_addr, data));
}
if desired_settings.contains(DesiredSensorSettings::HCNTRL_SEL) {
let gas_sett_heatr_ctrl = boundary_check(self.gas_sett.heatr_ctrl, 0x0u8, 0x8u8)?;
reg_addr = 0x70u8;
let mut data = self.get_regs_u8(reg_addr)?;
data = (data as (i32) & !0x8i32 | gas_sett_heatr_ctrl as (i32) & 0x8) as (u8) ;
reg.push((reg_addr, data));
}
/* Selecting heater T,P oversampling for the sensor */
if desired_settings
.contains(DesiredSensorSettings::OST_SEL | DesiredSensorSettings::OSP_SEL)
{
reg_addr = 0x74u8;
let mut data = self.get_regs_u8(reg_addr)?;
if desired_settings.contains(DesiredSensorSettings::OST_SEL) {
let tph_sett_os_temp = boundary_check(self.tph_sett.os_temp, 0, 5)?;
data = (data as (i32) & !0xe0i32 | tph_sett_os_temp as (i32) << 5i32 & 0xe0i32)
as (u8);
}
if desired_settings.contains(DesiredSensorSettings::OSP_SEL) {
let tph_sett_os_pres = self.tph_sett.os_temp.ok_or(Bme680Error::NulltPtr)?;
data = (data as (i32) & !0x1ci32 | tph_sett_os_pres as (i32) << 2i32 & 0x1ci32)
as (u8);
}
reg.push((reg_addr, data));
}
/* Selecting humidity oversampling for the sensor */
if desired_settings.contains(DesiredSensorSettings::OSH_SEL) {
let tph_sett_os_hum = boundary_check(self.tph_sett.os_hum, 0, 5)?;
reg_addr = 0x72u8;
let mut data = self.get_regs_u8(reg_addr)?;
data = (data as (i32) & !0x7i32 | tph_sett_os_hum as (i32) & 0x7i32) as (u8);
reg.push((reg_addr, data));
}
/* Selecting the runGas and NB conversion settings for the sensor */
if desired_settings
.contains(DesiredSensorSettings::RUN_GAS_SEL | DesiredSensorSettings::NBCONV_SEL)
{
reg_addr = 0x71u8;
let mut data = self.get_regs_u8(reg_addr)?;
if desired_settings.contains(DesiredSensorSettings::RUN_GAS_SEL) {
let gas_sett_run_gas = boundary_check(self.gas_sett.run_gas, 0, 1)?;
data = (data as (i32) & !0x10i32 | gas_sett_run_gas as (i32) << 4i32 & 0x10i32)
as (u8);
}
if desired_settings.contains(DesiredSensorSettings::NBCONV_SEL) {
let gas_sett_nb_conv = boundary_check(self.gas_sett.nb_conv, 0, 10)?;
data = (data as (i32) & !0xfi32 | gas_sett_nb_conv as (i32) & 0xfi32) as (u8);
}
reg.push((reg_addr, data));
}
self.bme680_set_regs(reg.as_slice())?;
/* Restore previous intended power mode */
self.power_mode = intended_power_mode;
Ok(())
}
// TODO replace desired_settings with proper flags type see lib.rs
pub fn get_sensor_settings(&mut self, desired_settings: u16) -> Result<SensorSettings> {
let reg_addr: u8 = 0x70u8;
let mut data_array: [u8; BME680_REG_BUFFER_LENGTH] = [0; BME680_REG_BUFFER_LENGTH];
let mut sensor_settings: SensorSettings = Default::default();
self.i2c.read(reg_addr, &mut data_array).map_err(|_| Bme680Error::CommunicationFailure)?;
if desired_settings & BME680_GAS_MEAS_SEL != 0 {
sensor_settings.gas_sett = self.get_gas_config()?;
}
if desired_settings & BME680_FILTER_SEL != 0 {
sensor_settings.tph_sett.filter =
Some(((data_array[5usize] as (i32) & 0x1ci32) >> 2i32) as (u8));
}
if desired_settings & (BME680_OST_SEL | BME680_OSP_SEL) != 0 {
sensor_settings.tph_sett.os_temp =
Some(((data_array[4usize] as (i32) & 0xe0i32) >> 5i32) as (u8));
sensor_settings.tph_sett.os_pres =
Some(((data_array[4usize] as (i32) & 0x1ci32) >> 2i32) as (u8));
}
if desired_settings & BME680_OSH_SEL != 0 {
sensor_settings.tph_sett.os_hum = Some((data_array[2usize] as (i32) & 0x7i32) as (u8));
}
if desired_settings & BME680_HCNTRL_SEL != 0 {
sensor_settings.gas_sett.heatr_ctrl = Some((data_array[0usize] as (i32) & 0x8i32) as (u8));
}
if desired_settings & (BME680_RUN_GAS_SEL | BME680_NBCONV_SEL) != 0 {
sensor_settings.gas_sett.nb_conv = Some((data_array[1usize] as (i32) & 0xfi32) as (u8));
sensor_settings.gas_sett.run_gas =
Some(((data_array[1usize] as (i32) & 0x10i32) >> 4i32) as (u8));
}
Ok(sensor_settings)
}
pub fn bme680_set_sensor_mode(&mut self, target_power_mode: PowerMode) -> Result<()> {
let mut tmp_pow_mode: u8;
let mut current_power_mode: PowerMode;
let reg_addr: u8 = 0x74u8;
/* Call repeatedly until in sleep */
loop {
tmp_pow_mode = self.get_regs_u8(BME680_CONF_T_P_MODE_ADDR)?;
/* Put to sleep before changing mode */
current_power_mode = PowerMode::from(tmp_pow_mode & BME680_MODE_MSK);
if current_power_mode != PowerMode::SleepMode {
/* Set to sleep*/
tmp_pow_mode = tmp_pow_mode & !BME680_MODE_MSK;
let reg = vec!((reg_addr, tmp_pow_mode));
self.bme680_set_regs(reg.as_slice())?;
self.delay.delay_ms(BME680_POLL_PERIOD_MS);
} else {
// TODO do while in Rust?
break;
}
}
/* Already in sleep */
if current_power_mode != PowerMode::SleepMode {
tmp_pow_mode = tmp_pow_mode & !BME680_MODE_MSK | target_power_mode.value();
self.bme680_set_regs(&[(reg_addr, tmp_pow_mode)])?;
}
Ok(())
}
pub fn get_sensor_mode(&mut self) -> Result<PowerMode> {
let regs = self.get_regs_u8(BME680_CONF_T_P_MODE_ADDR)?;
let mode = regs & BME680_MODE_MSK;
Ok(PowerMode::from(mode))
}
pub fn bme680_set_profile_dur(&mut self, tph_sett: TphSett, duration: u16) {
let os_to_meas_cycles: [u8; 6] = [0u8, 1u8, 2u8, 4u8, 8u8, 16u8];
// TODO check if the following unwrap_ors do not change behaviour
let mut meas_cycles = os_to_meas_cycles[tph_sett.os_temp.unwrap_or(0) as (usize)] as (u32);
meas_cycles =
meas_cycles.wrapping_add(os_to_meas_cycles[tph_sett.os_pres.unwrap_or(0) as (usize)] as (u32));
meas_cycles =
meas_cycles.wrapping_add(os_to_meas_cycles[tph_sett.os_hum.unwrap_or(0) as (usize)] as (u32));
let mut tph_dur = meas_cycles.wrapping_mul(1963u32);
tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(4u32));
tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(5u32));
tph_dur = tph_dur.wrapping_add(500u32);
tph_dur = tph_dur.wrapping_div(1000u32);
tph_dur = tph_dur.wrapping_add(1u32);
self.gas_sett.heatr_dur = Some((duration as (i32) - tph_dur as (u16) as (i32)) as (u16));
}
pub fn get_profile_dur(&self, tph_sett: TphSett, gas_sett: GasSett) -> Result<u16> {
let os_to_meas_cycles: [u8; 6] = [0u8, 1u8, 2u8, 4u8, 8u8, 16u8];
// TODO check if the following unwrap_ors do not change behaviour
let mut meas_cycles = os_to_meas_cycles[tph_sett.os_temp.unwrap_or(0) as (usize)] as (u32);
meas_cycles =
meas_cycles.wrapping_add(os_to_meas_cycles[tph_sett.os_pres.unwrap_or(0) as (usize)] as (u32));
meas_cycles =
meas_cycles.wrapping_add(os_to_meas_cycles[tph_sett.os_hum.unwrap_or(0) as (usize)] as (u32));
let mut tph_dur = meas_cycles.wrapping_mul(1963u32);
tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(4u32));
tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(5u32));
tph_dur = tph_dur.wrapping_add(500u32);
tph_dur = tph_dur.wrapping_div(1000u32);
tph_dur = tph_dur.wrapping_add(1u32);
let mut duration = tph_dur as (u16);
if gas_sett.run_gas.unwrap_or(0) != 0 {
duration = duration + gas_sett.heatr_dur.ok_or(Bme680Error::NulltPtr)?;
}
Ok(duration)
}
/// @returns (FieldData, IsNewFields)
pub fn get_sensor_data(&mut self) -> Result<(FieldData, FieldDataState)> {
let field_data = self.read_field_data()?;
if field_data.status & BME680_NEW_DATA_MSK != 0 {
// new fields
Ok((field_data, FieldDataState::NewData))
} else {
Ok((field_data, FieldDataState::NoNewData))
}
}
fn get_calib_data(&mut self) -> Result<CalibData> {
let mut calib: CalibData = Default::default();
let mut coeff_array: [u8; BME680_COEFF_SIZE] = [0; BME680_COEFF_SIZE];
self.i2c.read(
BME680_COEFF_ADDR1,
&mut coeff_array,
).map_err(|_| Bme680Error::CommunicationFailure)?;
self.i2c.read(
BME680_COEFF_ADDR2,
&mut coeff_array,
).map_err(|_| Bme680Error::CommunicationFailure)?;
calib.par_t1 = (coeff_array[34usize] as (u16) as (i32) << 8i32
| coeff_array[33usize] as (u16) as (i32)) as (u16);
calib.par_t2 = (coeff_array[2usize] as (u16) as (i32) << 8i32
| coeff_array[1usize] as (u16) as (i32)) as (i16);
calib.par_t3 = coeff_array[3usize] as (i8);
calib.par_p1 = (coeff_array[6usize] as (u16) as (i32) << 8i32
| coeff_array[5usize] as (u16) as (i32)) as (u16);
calib.par_p2 = (coeff_array[8usize] as (u16) as (i32) << 8i32
| coeff_array[7usize] as (u16) as (i32)) as (i16);
calib.par_p3 = coeff_array[9usize] as (i8);
calib.par_p4 = (coeff_array[12usize] as (u16) as (i32) << 8i32
| coeff_array[11usize] as (u16) as (i32)) as (i16);
calib.par_p5 = (coeff_array[14usize] as (u16) as (i32) << 8i32
| coeff_array[13usize] as (u16) as (i32)) as (i16);
calib.par_p6 = coeff_array[16usize] as (i8);
calib.par_p7 = coeff_array[15usize] as (i8);
calib.par_p8 = (coeff_array[20usize] as (u16) as (i32) << 8i32
| coeff_array[19usize] as (u16) as (i32)) as (i16);
calib.par_p9 = (coeff_array[22usize] as (u16) as (i32) << 8i32
| coeff_array[21usize] as (u16) as (i32)) as (i16);
calib.par_p10 = coeff_array[23usize];
calib.par_h1 = (coeff_array[27usize] as (u16) as (i32) << 4i32
| coeff_array[26usize] as (i32) & 0xfi32) as (u16);
calib.par_h2 = (coeff_array[25usize] as (u16) as (i32) << 4i32
| coeff_array[26usize] as (i32) >> 4i32) as (u16);
calib.par_h3 = coeff_array[28usize] as (i8);
calib.par_h4 = coeff_array[29usize] as (i8);
calib.par_h5 = coeff_array[30usize] as (i8);
calib.par_h6 = coeff_array[31usize];
calib.par_h7 = coeff_array[32usize] as (i8);
calib.par_gh1 = coeff_array[37usize] as (i8);
calib.par_gh2 = (coeff_array[36usize] as (u16) as (i32) << 8i32
| coeff_array[35usize] as (u16) as (i32)) as (i16);
calib.par_gh3 = coeff_array[38usize] as (i8);
calib.res_heat_range = (self.get_regs_u8(BME680_ADDR_RES_HEAT_RANGE_ADDR)? & 0x30) / 16;
calib.res_heat_val = self.get_regs_i8(BME680_ADDR_RES_HEAT_VAL_ADDR)?;
calib.range_sw_err = (self.get_regs_u8(BME680_ADDR_RANGE_SW_ERR_ADDR)? & BME680_RSERROR_MSK) / 16;
Ok(calib)
}
fn set_gas_config(&mut self, gas_sett: GasSett) -> Result<()> {
let mut reg = Vec::with_capacity(2);
if self.power_mode != PowerMode::ForcedMode {
return Err(Bme680Error::DefinePwrMode);
}
// TODO check whether unwrap_or changes behaviour
reg.push((BME680_RES_HEAT0_ADDR, self.calc_heater_res(gas_sett.heatr_temp.unwrap_or(0))));
reg.push((BME680_GAS_WAIT0_ADDR, self.calc_heater_dur(gas_sett.heatr_dur.unwrap_or(0))));
self.gas_sett.nb_conv = Some(0);
self.bme680_set_regs(reg.as_slice())
}
fn get_gas_config(&mut self) -> Result<GasSett> {
// TODO move both GasSett fields to new struct
let mut gas_sett: GasSett = Default::default();
// TODO figure out if heat_temp and dur can be u8
gas_sett.heatr_temp = Some(self.get_regs_u8(BME680_ADDR_SENS_CONF_START)? as u16);
gas_sett.heatr_dur = Some(self.get_regs_u8(BME680_ADDR_GAS_CONF_START)? as u16);
Ok(gas_sett)
}
fn calc_heater_res(&self, temp: u16) -> u8 {
// cap temperature
let temp = if temp <= 400 { temp } else { 400 };
let var1 = self.amb_temp as (i32) * self.calib.par_gh3 as (i32) / 1000i32 * 256i32;
let var2 = (self.calib.par_gh1 as (i32) + 784i32)
* (((self.calib.par_gh2 as (i32) + 154009i32) * temp as (i32) * 5i32 / 100i32
+ 3276800i32) / 10i32);
let var3 = var1 + var2 / 2i32;
let var4 = var3 / (self.calib.res_heat_range as (i32) + 4i32);
let var5 = 131i32 * self.calib.res_heat_val as (i32) + 65536i32;
let heatr_res_x100 = (var4 / var5 - 250i32) * 34i32;
((heatr_res_x100 + 50i32) / 100i32) as (u8)
}
fn calc_heater_dur(&self, dur: u16) -> u8 {
let mut factor: u8 = 0u8;
let mut dur = dur;
let durval =
if dur as (i32) >= 0xfc0i32 {
0xffu8 // Max duration
} else {
loop {
if !(dur as (i32) > 0x3fi32) {
break;
}
dur = (dur as (i32) / 4i32) as (u16);
factor = (factor as (i32) + 1i32) as (u8);
}
(dur as (i32) + factor as (i32) * 64i32) as (u8)
};
durval
}
fn calc_temperature(&mut self, temp_adc: u32) -> i16 {
let var1 = ((temp_adc as (i32) >> 3i32) - (self.calib.par_t1 as (i32) << 1i32)) as (isize);
let var2 = var1 * self.calib.par_t2 as (i32) as (isize) >> 11i32;
let var3 = (var1 >> 1i32) * (var1 >> 1i32) >> 12i32;
let var3 = var3 * (self.calib.par_t3 as (i32) << 4i32) as (isize) >> 14i32;
// TODO really assign here ?
self.calib.t_fine = (var2 + var3) as (i32);
let calc_temp = (self.calib.t_fine * 5i32 + 128i32 >> 8i32) as (i16);
calc_temp
}
fn calc_pressure(&self, pres_adc: u32) -> u32 {
let mut var1 = (self.calib.t_fine >> 1i32) - 64000i32;
let mut var2 = ((var1 >> 2i32) * (var1 >> 2i32) >> 11i32) * self.calib.par_p6 as (i32) >> 2i32;
var2 = var2 + (var1 * self.calib.par_p5 as (i32) << 1i32);
var2 = (var2 >> 2i32) + (self.calib.par_p4 as (i32) << 16i32);
var1 = (((var1 >> 2i32) * (var1 >> 2i32) >> 13i32) * (self.calib.par_p3 as (i32) << 5i32)
>> 3i32) + (self.calib.par_p2 as (i32) * var1 >> 1i32);
var1 = var1 >> 18i32;
var1 = (32768i32 + var1) * self.calib.par_p1 as (i32) >> 15i32;
let mut pressure_comp = 1048576u32.wrapping_sub(pres_adc) as (i32);
pressure_comp = ((pressure_comp - (var2 >> 12i32)) as (u32)).wrapping_mul(3125u32) as (i32);
if pressure_comp >= 0x40000000i32 {
pressure_comp = ((pressure_comp as (u32)).wrapping_div(var1 as (u32)) << 1i32) as (i32);
} else {
pressure_comp = ((pressure_comp << 1i32) as (u32)).wrapping_div(var1 as (u32)) as (i32);
}
var1 = self.calib.par_p9 as (i32)
* ((pressure_comp >> 3i32) * (pressure_comp >> 3i32) >> 13i32) >> 12i32;
var2 = (pressure_comp >> 2i32) * self.calib.par_p8 as (i32) >> 13i32;
let var3 = (pressure_comp >> 8i32) * (pressure_comp >> 8i32) * (pressure_comp >> 8i32)
* self.calib.par_p10 as (i32) >> 17i32;
pressure_comp =
pressure_comp + (var1 + var2 + var3 + (self.calib.par_p7 as (i32) << 7i32) >> 4i32);
pressure_comp as (u32)
}
fn calc_humidity(&self, hum_adc: u16) -> u32 {
let temp_scaled = self.calib.t_fine * 5i32 + 128i32 >> 8i32;
let var1 = hum_adc as (i32) - self.calib.par_h1 as (i32) * 16i32
- (temp_scaled * self.calib.par_h3 as (i32) / 100i32 >> 1i32);
let var2 = self.calib.par_h2 as (i32)
* (temp_scaled * self.calib.par_h4 as (i32) / 100i32
+ (temp_scaled * (temp_scaled * self.calib.par_h5 as (i32) / 100i32) >> 6i32)
/ 100i32 + (1i32 << 14i32)) >> 10i32;
let var3 = var1 * var2;
let var4 = self.calib.par_h6 as (i32) << 7i32;
let var4 = var4 + temp_scaled * self.calib.par_h7 as (i32) / 100i32 >> 4i32;
let var5 = (var3 >> 14i32) * (var3 >> 14i32) >> 10i32;
let var6 = var4 * var5 >> 1i32;
let mut calc_hum = (var3 + var6 >> 10i32) * 1000i32 >> 12i32;
if calc_hum > 100000i32 {
calc_hum = 100000i32;
} else if calc_hum < 0i32 {
calc_hum = 0i32;
}
calc_hum as (u32)
}
fn calc_gas_resistance(&mut self, gas_res_adc: u16, gas_range: u8) -> u32 {
let lookupTable1: [u32; 16] = [
2147483647u32,
2147483647u32,
2147483647u32,
2147483647u32,
2147483647u32,
2126008810u32,
2147483647u32,
2130303777u32,
2147483647u32,
2147483647u32,
2143188679u32,
2136746228u32,
2147483647u32,
2126008810u32,
2147483647u32,
2147483647u32,
];
let lookupTable2: [u32; 16] = [
4096000000u32,
2048000000u32,
1024000000u32,
512000000u32,
255744255u32,
127110228u32,
64000000u32,
32258064u32,
16016016u32,
8000000u32,
4000000u32,
2000000u32,
1,
500000u32,
250000u32,
125000u32,
];
let var1 = (1340isize + 5isize * self.calib.range_sw_err as (isize))
* lookupTable1[gas_range as (usize)] as (isize) >> 16i32;
let var2 = ((gas_res_adc as (isize) << 15i32) - 16777216isize + var1) as (usize);
let var3 = lookupTable2[gas_range as (usize)] as (isize) * var1 >> 9i32;
let calc_gas_res = ((var3 + (var2 as (isize) >> 1i32)) / var2 as (isize)) as (u32);
calc_gas_res
}
fn read_field_data(&mut self) -> Result<FieldData> {
let mut buff = [0, BME680_FIELD_LENGTH];
let mut data: FieldData = Default::default();
let mut gas_range: u8;
let mut adc_temp: u32;
let mut adc_pres: u32;
let mut adc_hum: u16;
let mut adc_gas_res: u16;
let mut tries: u8 = 10u8;
loop {
self.i2c.read(BME680_FIELD0_ADDR, &mut buff)
.map_err(|_| Bme680Error::CommunicationFailure)?;
data.status = buff[0] & BME680_NEW_DATA_MSK;
data.gas_index = buff[0] & BME680_GAS_INDEX_MSK;;
data.meas_index = buff[1];
adc_pres = (buff[2] as (u32)).wrapping_mul(4096) | (buff[3] as (u32)).wrapping_mul(16)
| (buff[4] as (u32)).wrapping_div(16);
adc_temp = (buff[5] as (u32)).wrapping_mul(4096) | (buff[6] as (u32)).wrapping_mul(16)
| (buff[7] as (u32)).wrapping_div(16);
adc_hum = ((buff[8] as (u32)).wrapping_mul(256) | buff[9] as (u32)) as (u16);
adc_gas_res = ((buff[13] as (u32)).wrapping_mul(4)
| (buff[14] as (u32)).wrapping_div(64)) as (u16);
gas_range = buff[14] & BME680_GAS_RANGE_MSK;
data.status = data.status | buff[14] & BME680_GASM_VALID_MSK;
data.status = data.status | buff[14] & BME680_HEAT_STAB_MSK;
if data.status & BME680_NEW_DATA_MSK != 0 {
data.temperature = self.calc_temperature(adc_temp);
data.pressure = self.calc_pressure(adc_pres);
data.humidity = self.calc_humidity(adc_hum);
data.gas_resistance = self.calc_gas_resistance(adc_gas_res, gas_range);
return Ok(data);
}
self.delay.delay_ms(BME680_POLL_PERIOD_MS);
tries = tries - 1;
if tries == 0 {
break;
}
}
Err(Bme680Error::NoNewData)
}
}

View file

@ -1,34 +0,0 @@
pub const BME680_OK: i8 = 0;
pub const BME680_E_NULL_PTR: i8 = -1;
pub const BME680_E_COM_FAIL: i8 = -2;
pub const BME680_E_DEV_NOT_FOUND: i8 = -3;
pub const BME680_E_INVALID_LENGTH: i8 = -4;
pub const BME680_I2C_ADDR_PRIMARY: u8 = 0x76;
pub const BME680_I2C_ADDR_SECONDARY: u8 = 0x77;
pub const BME680_CHIP_ID: u8 = 0x61;
pub const BME680_SLEEP_MODE: u8 = 0;
pub const BME680_FORCED_MODE: u8 = 1;
///
/// SPI memory page settings
///
pub const BME680_MEM_PAGE0: u8 = 0x10;
///
/// SPI memory page settings
///
pub const BME680_MEM_PAGE1: u8 = 0x00;
/* Settings selector */
pub const BME680_OST_SEL: u16 = 1;
pub const BME680_OSP_SEL: u16 = 2;
pub const BME680_OSH_SEL: u16 = 4;
pub const BME680_GAS_MEAS_SEL: u16 = 8;
pub const BME680_FILTER_SEL: u16 = 16;
pub const BME680_HCNTRL_SEL: u16 = 32;
pub const BME680_RUN_GAS_SEL: u16 = 64;
pub const BME680_NBCONV_SEL: u16 = 128;
pub const BME680_GAS_SENSOR_SEL: u16 = BME680_GAS_MEAS_SEL | BME680_RUN_GAS_SEL | BME680_NBCONV_SEL;

View file

@ -1,398 +0,0 @@
use hal::blocking::delay::DelayMs;
use hal::blocking::i2c::{Read, Write, WriteRead};
use consts;
use {to_result, PowerMode, Result, SensorSettings, bme680_calib_data, bme680_dev,
bme680_field_data, bme680_gas_sett, bme680_get_profile_dur, bme680_get_regs,
bme680_get_sensor_data, bme680_get_sensor_mode, bme680_get_sensor_settings, bme680_init,
bme680_intf, bme680_intf_BME680_I2C_INTF, bme680_set_profile_dur, bme680_set_sensor_mode,
bme680_set_sensor_settings, bme680_soft_reset, bme680_tph_sett};
impl Default for bme680_field_data {
fn default() -> bme680_field_data {
bme680_field_data {
status: Default::default(),
/// The index of the heater profile used
gas_index: Default::default(),
/// Measurement index to track order
meas_index: Default::default(),
/// Temperature in degree celsius x100
temperature: Default::default(),
/// Pressure in Pascal
pressure: Default::default(),
/// Humidity in % relative humidity x1000
humidity: Default::default(),
/// Gas resistance in Ohms
gas_resistance: Default::default(),
}
}
}
pub struct Bme680Device {
dev: bme680_dev,
}
impl Bme680Device {
/// @brief This API is the entry point.
/// It reads the chip-id and calibration data from the sensor.
///
/// @param[in,out] dev : Structure instance of bme680_dev
///
/// @return Result of API execution status
pub fn init(mut self) -> Result<()> {
let dev_ptr: *mut bme680_dev = &mut self.dev;
unsafe { to_result(bme680_init(dev_ptr)) }
}
/// @brief This API writes the given data to the register address
/// of the sensor.
///
/// @param[in] reg_addr : Register address from where the data to be written.
/// @param[in] reg_data : Pointer to data buffer which is to be written
/// in the sensor.
/// @param[in] len : No of bytes of data to write..
/// @param[in] dev : Structure instance of bme680_dev.
///
/// @return Result of API execution status
pub fn set_regs(mut self, reg_addr: u8, reg_data: &mut [u8]) -> Result<()> {
let dev_ptr: *mut bme680_dev = &mut self.dev;
unsafe {
to_result(bme680_get_regs(
reg_addr,
reg_data.as_mut_ptr(),
reg_data.len() as u16,
dev_ptr,
))
}
}
/// @brief This API reads the data from the given register address of the sensor.
///
/// @param[in] reg_addr : Register address from where the data to be read
/// @param[out] reg_data : buffer to store the read data.
///
/// @return Result of API execution status
pub fn get_regs(mut self, reg_addr: u8, reg_data: &mut [u8]) -> Result<()> {
let dev_ptr: *mut bme680_dev = &mut self.dev;
unsafe {
to_result(bme680_get_regs(
reg_addr,
reg_data.as_mut_ptr(),
reg_data.len() as u16,
dev_ptr,
))
}
}
/// @brief This API performs the soft reset of the sensor.
///
/// @return Result of API execution status
pub fn soft_reset(mut self) -> Result<()> {
let dev_ptr: *mut bme680_dev = &mut self.dev;
unsafe { to_result(bme680_soft_reset(dev_ptr)) }
}
/// @brief This API is used to set the power mode of the sensor.
///
/// @param[in] power_mode : Sensor power mode
///
/// @return Result of API execution status
pub fn set_sensor_mode(mut self, power_mode: PowerMode) -> Result<()> {
self.dev.power_mode = power_mode.value();
let dev_ptr: *mut bme680_dev = &mut self.dev;
unsafe { to_result(bme680_set_sensor_mode(dev_ptr)) }
}
/// @brief This API is used to get the power mode of the sensor.
///
/// @return Sensor power mode
pub fn get_sensor_mode(mut self) -> Result<PowerMode> {
let dev_ptr: *mut bme680_dev = &mut self.dev;
let r = unsafe { to_result(bme680_get_sensor_mode(dev_ptr)) };
r.map(|_| PowerMode::from(self.dev.power_mode))
}
/// @brief This API is used to set the profile duration of the sensor.
///
/// @param[in] duration : Duration of the measurement in ms.
pub fn set_profile_dur(mut self, duration: u16) {
let dev_ptr: *mut bme680_dev = &mut self.dev;
unsafe { bme680_set_profile_dur(duration, dev_ptr) }
}
/// @brief This API is used to get the profile duration of the sensor.
///
/// @return Duration of the measurement in ms.
pub fn get_profile_dur(mut self) -> u16 {
let dev_ptr: *mut bme680_dev = &mut self.dev;
let mut duration = 0;
unsafe { bme680_get_profile_dur(&mut duration, dev_ptr) };
duration
}
/// @brief This API reads the pressure, temperature and humidity and gas data
/// from the sensor, compensates the data and store it in the bme680_data
/// structure instance passed by the user.
///
/// @param[out] data: Structure instance to hold the data.
/// @param[in] dev : Structure instance of bme680_dev.
///
/// @return Result of API execution status
pub fn get_sensor_data(mut self) -> Result<bme680_field_data> {
let dev_ptr: *mut bme680_dev = &mut self.dev;
let mut field_data = Default::default();
let field_data_ptr: *mut bme680_field_data = &mut field_data;
let r = unsafe { to_result(bme680_get_sensor_data(field_data_ptr, dev_ptr)) };
r.map(|_| field_data)
}
/// @brief This API is used to set the oversampling, filter and T,P,H, gas selection
/// settings in the sensor.
///
/// @param[in] desired_settings : Variable used to select the settings which
/// @return Result of API execution status
pub fn set_sensor_settings(mut self, sensor_settings: SensorSettings) -> Result<()> {
let dev_ptr: *mut bme680_dev = &mut self.dev;
unsafe { to_result(bme680_set_sensor_settings(sensor_settings.bits(), dev_ptr)) }
}
pub fn get_tph_sett(mut self) -> Result<bme680_tph_sett> {
let dev_ptr: *mut bme680_dev = &mut self.dev;
let settings_sel = SensorSettings::OST_SEL | SensorSettings::OSP_SEL
| SensorSettings::OSH_SEL | SensorSettings::FILTER_SEL;
let r = unsafe { to_result(bme680_get_sensor_settings(settings_sel.bits(), dev_ptr)) };
r.map(|_| self.dev.tph_sett)
}
pub fn get_gas_sett(mut self) -> Result<bme680_gas_sett> {
let dev_ptr: *mut bme680_dev = &mut self.dev;
let settings_sel = SensorSettings::GAS_SENSOR_SEL;
let r = unsafe { to_result(bme680_get_sensor_settings(settings_sel.bits(), dev_ptr)) };
r.map(|_| self.dev.gas_sett)
}
}
impl Default for bme680_calib_data {
fn default() -> bme680_calib_data {
bme680_calib_data {
/// Variable to store calibrated humidity data
par_h1: Default::default(),
/// Variable to store calibrated humidity data
par_h2: Default::default(),
/// Variable to store calibrated humidity data
par_h3: Default::default(),
/// Variable to store calibrated humidity data
par_h4: Default::default(),
/// Variable to store calibrated humidity data
par_h5: Default::default(),
/// Variable to store calibrated humidity data
par_h6: Default::default(),
/// Variable to store calibrated humidity data
par_h7: Default::default(),
/// Variable to store calibrated gas data
par_gh1: Default::default(),
/// Variable to store calibrated gas data
par_gh2: Default::default(),
/// Variable to store calibrated gas data
par_gh3: Default::default(),
/// Variable to store calibrated temperature data
par_t1: Default::default(),
/// Variable to store calibrated temperature data
par_t2: Default::default(),
/// Variable to store calibrated temperature data
par_t3: Default::default(),
/// Variable to store calibrated pressure data
par_p1: Default::default(),
/// Variable to store calibrated pressure data
par_p2: Default::default(),
/// Variable to store calibrated pressure data
par_p3: Default::default(),
/// Variable to store calibrated pressure data
par_p4: Default::default(),
/// Variable to store calibrated pressure data
par_p5: Default::default(),
/// Variable to store calibrated pressure data
par_p6: Default::default(),
/// Variable to store calibrated pressure data
par_p7: Default::default(),
/// Variable to store calibrated pressure data
par_p8: Default::default(),
/// Variable to store calibrated pressure data
par_p9: Default::default(),
/// Variable to store calibrated pressure data
par_p10: Default::default(),
/// Variable to store t_fine size
t_fine: Default::default(),
/// Variable to store heater resistance range
res_heat_range: Default::default(),
/// Variable to store heater resistance value
res_heat_val: Default::default(),
/// Variable to store error range
range_sw_err: Default::default(),
}
}
}
impl Default for bme680_gas_sett {
fn default() -> bme680_gas_sett {
bme680_gas_sett {
/// Variable to store nb conversion
nb_conv: Default::default(),
/// Variable to store heater control
heatr_ctrl: Default::default(),
/// Run gas enable value
run_gas: Default::default(),
/// Heater temperature value
heatr_temp: Default::default(),
/// Duration profile value
heatr_dur: Default::default(),
}
}
}
impl Default for bme680_tph_sett {
fn default() -> bme680_tph_sett {
bme680_tph_sett {
/// Humidity oversampling
os_hum: Default::default(),
/// Temperature oversampling
os_temp: Default::default(),
/// Pressure oversampling
os_pres: Default::default(),
/// Filter coefficient
filter: Default::default(),
}
}
}
pub struct Bme680DeviceBuilder<I2C, D> {
dev: bme680_dev,
}
/// Generic communication function pointer
/// @param[in] dev_id: Place holder to store the id of the device structure
/// Can be used to store the index of the Chip select or
/// I2C address of the device.
/// @param[in] reg_addr: Used to select the register the where data needs to
/// be read from or written to.
/// @param[in/out] reg_data: Data array to read/write
/// @param[in] len: Length of the data array
type ComFn = extern "C" fn(dev_id: u8, reg_addr: u8, data: *mut u8, len: u16) -> i8;
type DelayFn = extern "C" fn(period: u32);
impl<I2C, D, E> Bme680DeviceBuilder<I2C, D> where
I2C: Read<Error = E> + Write<Error = E> + WriteRead<Error = E>,
D: DelayMs<u8>,
{
pub fn new(i2c: I2C, delay: D) -> Self {
let dev = bme680_dev {
/// Chip Id
chip_id: consts::BME680_CHIP_ID,
/// Device Id
dev_id: consts::BME680_I2C_ADDR_PRIMARY,
/// SPI/I2C interface
intf: bme680_intf_BME680_I2C_INTF,
/// Memory page used
mem_page: Default::default(),
/// Ambient temperature in Degree C
amb_temp: Default::default(),
/// Sensor calibration data
calib: Default::default(),
/// Sensor settings
tph_sett: Default::default(),
/// Gas Sensor settings
gas_sett: Default::default(),
/// Sensor power modes
power_mode: consts::BME680_SLEEP_MODE,
/// New sensor fields
new_fields: Default::default(),
/// Store the info messages
info_msg: Default::default(),
fn read(
&mut self,
address: u8,
buffer: &mut [u8]
) -> Result<(), Self::Error>;
extern "C" fn ( dev_id : u8 , reg_addr : u8 , data : * mut u8 , len : u16 ) -> i8
/// Bus read function pointer
read: Some(read),
/// Bus write function pointer
write: Some(write),
/// delay function pointer
delay_ms: Some(delay.delay_ms),
/// Communication function result
com_rslt: Default::default(),
};
Self { dev: dev }
}
pub fn with_chip_id(mut self, chip_id: u8) -> Self {
self.dev.chip_id = chip_id;
self
}
pub fn with_dev_id(mut self, dev_id: u8) -> Self {
self.dev.dev_id = dev_id;
self
}
pub fn with_intf(mut self, intf: bme680_intf) -> Self {
self.dev.intf = intf;
self
}
pub fn with_mem_page(mut self, mem_page: u8) -> Self {
self.dev.mem_page = mem_page;
self
}
pub fn with_amb_temp(mut self, amb_temp: i8) -> Self {
self.dev.amb_temp = amb_temp;
self
}
pub fn with_calib(mut self, calib: bme680_calib_data) -> Self {
self.dev.calib = calib;
self
}
pub fn with_tph_sett(mut self, tph_sett: bme680_tph_sett) -> Self {
self.dev.tph_sett = tph_sett;
self
}
pub fn with_gas_sett(mut self, gas_sett: bme680_gas_sett) -> Self {
self.dev.gas_sett = gas_sett;
self
}
pub fn with_power_mode(mut self, power_mode: u8) -> Self {
self.dev.power_mode = power_mode;
self
}
pub fn with_new_fields(mut self, new_fields: u8) -> Self {
self.dev.new_fields = new_fields;
self
}
pub fn with_info_msg(mut self, info_msg: u8) -> Self {
self.dev.info_msg = info_msg;
self
}
pub fn with_com_rslt(mut self, com_rslt: i8) -> Self {
self.dev.com_rslt = com_rslt;
self
}
pub fn build(self) -> Bme680Device {
Bme680Device { dev: self.dev }
}
}

View file

@ -1,47 +1,128 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![feature(rustc_private)]
#![feature(try_from)] #![feature(try_from)]
//include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
extern crate byteorder;
extern crate embedded_hal as hal; extern crate embedded_hal as hal;
use hal::blocking::delay::{DelayMs, DelayUs}; use hal::blocking::delay::DelayMs;
use hal::blocking::i2c::{Read, Write};
use std::convert::TryFrom;
use std::result; use std::result;
#[link(name = "example", kind = "static")] /** BME680 General config */
mod consts; pub const BME680_POLL_PERIOD_MS: u8 = 10;
//mod device_builder;
mod bme680;
#[cfg(test)] /** BME680 I2C addresses */
mod tests { pub const BME680_I2C_ADDR_PRIMARY: u8 = 0x76;
pub const BME680_I2C_ADDR_SECONDARY: u8 = 0x77;
use device_builder::Bme680DeviceBuilder; /** BME680 unique chip identifier */
pub const BME680_CHIP_ID: u8 = 0x61;
extern "C" fn com(dev_id: u8, reg_addr: u8, data: *mut u8, len: u16) -> i8 { /** BME680 coefficients related defines */
0 pub const BME680_COEFF_SIZE: usize = 41;
} pub const BME680_COEFF_ADDR1_LEN: u8 = 25;
pub const BME680_COEFF_ADDR2_LEN: u8 = 16;
extern "C" fn delay(period: u32) { /** BME680 field_x related defines */
println!("delay {}", period); pub const BME680_FIELD_LENGTH: u8 = 15;
} pub const BME680_FIELD_ADDR_OFFSET: u8 = 17;
#[test] pub const BME680_SOFT_RESET_CMD: u8 = 0xb6;
fn init() {
let dev = Bme680DeviceBuilder::new(com, com, delay).build();
dev.init();
}
}
pub type Result<T> = result::Result<T, Bme680Error>; pub const BME680_OK: i8 = 0;
/** Errors **/
pub const BME680_E_NULL_PTR: i8 = -1;
pub const BME680_E_COM_FAIL: i8 = -2;
pub const BME680_E_DEV_NOT_FOUND: i8 = -3;
pub const BME680_E_INVALID_LENGTH: i8 = -4;
/** Register map */
/** Other coefficient's address */
pub const BME680_ADDR_RES_HEAT_VAL_ADDR: u8 = 0x00;
pub const BME680_ADDR_RES_HEAT_RANGE_ADDR: u8 = 0x02;
pub const BME680_ADDR_RANGE_SW_ERR_ADDR: u8 = 0x04;
pub const BME680_ADDR_SENS_CONF_START: u8 = 0x5A;
pub const BME680_ADDR_GAS_CONF_START: u8 = 0x64;
pub const BME680_SOFT_RESET_ADDR: u8 = 0xe0;
/** Field settings */
pub const BME680_FIELD0_ADDR: u8 = 0x1d;
/** Heater settings */
pub const BME680_RES_HEAT0_ADDR: u8 = 0x5a;
pub const BME680_GAS_WAIT0_ADDR: u8 = 0x64;
/** Sensor configuration registers */
pub const BME680_CONF_HEAT_CTRL_ADDR: u8 = 0x70;
pub const BME680_CONF_ODR_RUN_GAS_NBC_ADDR: u8 = 0x71;
pub const BME680_CONF_OS_H_ADDR: u8 = 0x72;
pub const BME680_MEM_PAGE_ADDR: u8 = 0xf3;
pub const BME680_CONF_T_P_MODE_ADDR: u8 = 0x74;
pub const BME680_CONF_ODR_FILT_ADDR: u8 = 0x75;
/** Coefficient's address */
pub const BME680_COEFF_ADDR1: u8 = 0x89;
pub const BME680_COEFF_ADDR2: u8 = 0xe1;
/** Chip identifier */
pub const BME680_CHIP_ID_ADDR: u8 = 0xd0;
pub const BME680_SLEEP_MODE: u8 = 0;
pub const BME680_FORCED_MODE: u8 = 1;
pub const BME680_RESET_PERIOD: u8 = 10;
pub const BME680_GAS_MEAS_MSK: u8 = 0x30;
pub const BME680_NBCONV_MSK: u8 = 0x0F;
pub const BME680_FILTER_MSK: u8 = 0x1C;
pub const BME680_OST_MSK: u8 = 0xE0;
pub const BME680_OSP_MSK: u8 = 0x1C;
pub const BME680_OSH_MSK: u8 = 0x07;
pub const BME680_HCTRL_MSK: u8 = 0x08;
pub const BME680_RUN_GAS_MSK: u8 = 0x10;
pub const BME680_MODE_MSK: u8 = 0x03;
pub const BME680_RHRANGE_MSK: u8 = 0x30;
pub const BME680_RSERROR_MSK: u8 = 0xf0;
pub const BME680_NEW_DATA_MSK: u8 = 0x80;
pub const BME680_GAS_INDEX_MSK: u8 = 0x0f;
pub const BME680_GAS_RANGE_MSK: u8 = 0x0f;
pub const BME680_GASM_VALID_MSK: u8 = 0x20;
pub const BME680_HEAT_STAB_MSK: u8 = 0x10;
pub const BME680_MEM_PAGE_MSK: u8 = 0x10;
pub const BME680_SPI_RD_MSK: u8 = 0x80;
pub const BME680_SPI_WR_MSK: u8 = 0x7f;
pub const BME680_BIT_H1_DATA_MSK: u8 = 0x0F;
///
/// SPI memory page settings
///
pub const BME680_MEM_PAGE0: u8 = 0x10;
///
/// SPI memory page settings
///
pub const BME680_MEM_PAGE1: u8 = 0x00;
/** Buffer length macro declaration */
pub const BME680_TMP_BUFFER_LENGTH: usize = 40;
pub const BME680_REG_BUFFER_LENGTH: usize = 6;
pub const BME680_FIELD_DATA_LENGTH: usize = 3;
pub const BME680_GAS_REG_BUF_LENGTH: usize = 20;
/* Settings selector */
pub const BME680_OST_SEL: u16 = 1;
pub const BME680_OSP_SEL: u16 = 2;
pub const BME680_OSH_SEL: u16 = 4;
pub const BME680_GAS_MEAS_SEL: u16 = 8;
pub const BME680_FILTER_SEL: u16 = 16;
pub const BME680_HCNTRL_SEL: u16 = 32;
pub const BME680_RUN_GAS_SEL: u16 = 64;
pub const BME680_NBCONV_SEL: u16 = 128;
pub const BME680_GAS_SENSOR_SEL: u16 = BME680_GAS_MEAS_SEL | BME680_RUN_GAS_SEL | BME680_NBCONV_SEL;
pub enum Bme680Error { pub enum Bme680Error {
/// ///
@ -60,26 +141,161 @@ pub enum Bme680Error {
/// aka BME680_E_INVALID_LENGTH /// aka BME680_E_INVALID_LENGTH
/// ///
InvalidLength, InvalidLength,
///
/// Warning aka BME680_W_DEFINE_PWR_MODE
///
DefinePwrMode,
///
/// Warning aka BME680_W_DEFINE_PWR_MODE
///
NoNewData,
///
/// Warning Boundary Check
///
BoundaryCheckFailure(InfoMsg, u8, u8),
} }
fn to_result(res: i8) -> Result<()> { pub type Result<T> = result::Result<T, Bme680Error>;
match res {
consts::BME680_OK => Ok(()), ///
consts::BME680_E_NULL_PTR => Err(Bme680Error::NulltPtr), /// Power mode settings
consts::BME680_E_COM_FAIL => Err(Bme680Error::CommunicationFailure), ///
consts::BME680_E_DEV_NOT_FOUND => Err(Bme680Error::DeviceNotFound), #[derive(PartialEq, Clone, Copy)]
consts::BME680_E_INVALID_LENGTH => Err(Bme680Error::InvalidLength), pub enum PowerMode {
_ => panic!("Invalid bme680 result: {}", res), SleepMode,
ForcedMode,
}
impl PowerMode {
fn from(power_mode: u8) -> Self {
match power_mode {
BME680_SLEEP_MODE => PowerMode::SleepMode,
BME680_FORCED_MODE => PowerMode::ForcedMode,
_ => panic!("Unknown power mode: {}", power_mode),
}
}
fn value(&self) -> u8 {
match self {
PowerMode::SleepMode => BME680_SLEEP_MODE,
PowerMode::ForcedMode => BME680_FORCED_MODE,
}
} }
} }
pub enum I2CAddr { #[derive(Default, Copy)]
Primary, #[repr(C)]
Secondary, pub struct CalibData {
pub par_h1: u16,
pub par_h2: u16,
pub par_h3: i8,
pub par_h4: i8,
pub par_h5: i8,
pub par_h6: u8,
pub par_h7: i8,
pub par_gh1: i8,
pub par_gh2: i16,
pub par_gh3: i8,
pub par_t1: u16,
pub par_t2: i16,
pub par_t3: i8,
pub par_p1: u16,
pub par_p2: i16,
pub par_p3: i8,
pub par_p4: i16,
pub par_p5: i16,
pub par_p6: i8,
pub par_p7: i8,
pub par_p8: i16,
pub par_p9: i16,
pub par_p10: u8,
pub t_fine: i32,
pub res_heat_range: u8,
pub res_heat_val: i8,
pub range_sw_err: u8,
}
impl Clone for CalibData {
fn clone(&self) -> Self {
*self
}
}
#[derive(Default, Copy)]
#[repr(C)]
pub struct TphSett {
pub os_hum: Option<u8>,
pub os_temp: Option<u8>,
pub os_pres: Option<u8>,
pub filter: Option<u8>,
}
impl Clone for TphSett {
fn clone(&self) -> Self {
*self
}
}
#[derive(Default, Copy)]
#[repr(C)]
pub struct GasSett {
pub nb_conv: Option<u8>,
pub heatr_ctrl: Option<u8>,
pub run_gas: Option<u8>,
pub heatr_temp: Option<u16>,
pub heatr_dur: Option<u16>,
}
impl Clone for GasSett {
fn clone(&self) -> Self {
*self
}
}
#[derive(Default, Copy)]
#[repr(C)]
pub struct FieldData {
pub status: u8,
pub gas_index: u8,
pub meas_index: u8,
pub temperature: i16,
pub pressure: u32,
pub humidity: u32,
pub gas_resistance: u32,
}
impl Clone for FieldData {
fn clone(&self) -> Self {
*self
}
}
/// TODO - replace naming of "State" with something better
/// aka new_fields - BME680_NEW_DATA_MSK
///
pub enum FieldDataState {
NewData,
// TODO find better naming to no new data
NoNewData,
}
/// Infos
bitflags! {
#[derive(Default)]
pub struct InfoMsg: u8 {
const MIN_CORRECTION = 1;
const MAX_CORRECTION = 2;
}
}
#[derive(Default)]
pub struct SensorSettings {
gas_sett: GasSett,
tph_sett: TphSett,
} }
bitflags! { bitflags! {
pub struct SensorSettings: u16 { pub struct DesiredSensorSettings: u16 {
/// To set temperature oversampling /// To set temperature oversampling
const OST_SEL = 1; const OST_SEL = 1;
/// To set pressure oversampling. /// To set pressure oversampling.
@ -101,3 +317,590 @@ bitflags! {
const GAS_SENSOR_SEL = Self::GAS_MEAS_SEL.bits | Self::RUN_GAS_SEL.bits | Self::NBCONV_SEL.bits; const GAS_SENSOR_SEL = Self::GAS_MEAS_SEL.bits | Self::RUN_GAS_SEL.bits | Self::NBCONV_SEL.bits;
} }
} }
#[repr(C)]
pub struct Bme680_dev<I2C, D> {
pub i2c: I2C,
pub delay: D,
pub dev_id: u8,
pub mem_page: u8,
pub amb_temp: i8,
pub calib: CalibData,
pub tph_sett: TphSett,
pub gas_sett: GasSett,
pub power_mode: PowerMode,
pub new_fields: u8,
pub info_msg: u8,
}
fn boundary_check(value: Option<u8>, min: u8, max: u8) -> Result<u8> {
let mut info_msg: InfoMsg = Default::default();
// TODO give the nullptr here a different name
let value = value.ok_or(Bme680Error::NulltPtr)?;
if value < min {
info_msg |= InfoMsg::MIN_CORRECTION;
}
if value > max {
info_msg |= InfoMsg::MAX_CORRECTION;
}
if info_msg.is_empty() {
return Err(Bme680Error::BoundaryCheckFailure(info_msg, min, max));
}
Ok(value)
}
impl<I2C, D> Bme680_dev<I2C, D>
where
D: DelayMs<u8>,
I2C: Read + Write,
{
pub fn init(&mut self) -> Result<()> {
self.soft_reset()?;
/* Soft reset to restore it to default values*/
let chip_id = self.get_regs_u8(BME680_CHIP_ID_ADDR)?;
if chip_id == BME680_CHIP_ID {
self.calib = self.get_calib_data()?;
Ok(())
} else {
Err(Bme680Error::DeviceNotFound)
}
}
pub fn get_regs_u8(&mut self, reg_addr: u8) -> Result<u8> {
let mut buf = [0; 1];
match self.i2c.read(reg_addr, &mut buf) {
Ok(()) => Ok(buf[0]),
Err(_) => Err(Bme680Error::CommunicationFailure),
}
}
pub fn get_regs_i8(&mut self, reg_addr: u8) -> Result<i8> {
let mut buf = [0; 1];
match self.i2c.read(reg_addr, &mut buf) {
Ok(()) => Ok(i8::try_from(buf[0]).expect("U8 overflow when reading register")),
Err(_) => Err(Bme680Error::CommunicationFailure),
}
}
pub fn bme680_set_regs(&mut self, reg: &[(u8, u8)]) -> Result<()> {
if reg.is_empty() || reg.len() > (BME680_TMP_BUFFER_LENGTH / 2) as usize {
return Err(Bme680Error::InvalidLength);
}
let mut tmp_buff = Vec::with_capacity(BME680_TMP_BUFFER_LENGTH);
for (reg_addr, reg_data) in reg {
tmp_buff.push(reg_addr.to_owned());
tmp_buff.push(reg_data.to_owned());
}
self.i2c
.write(self.dev_id, tmp_buff.as_slice())
.map_err(|_| Bme680Error::CommunicationFailure)
}
pub fn soft_reset(&mut self) -> Result<()> {
self.bme680_set_regs(&[(BME680_SOFT_RESET_ADDR, BME680_SOFT_RESET_CMD)])?;
self.delay.delay_ms(BME680_RESET_PERIOD);
Ok(())
}
// TODO replace parameter desired_settings with safe flags
pub fn bme680_set_sensor_settings(
&mut self,
desired_settings: DesiredSensorSettings,
gas_sett: Option<GasSett>,
) -> Result<()> {
let mut reg_addr: u8;
let mut reg = Vec::with_capacity(BME680_REG_BUFFER_LENGTH);
let intended_power_mode = self.power_mode;
if desired_settings.contains(DesiredSensorSettings::GAS_MEAS_SEL) {
self.set_gas_config(gas_sett.unwrap())?;
}
let power_mode = self.power_mode;
self.bme680_set_sensor_mode(power_mode)?;
/* Selecting the filter */
if desired_settings.contains(DesiredSensorSettings::FILTER_SEL) {
let tph_sett_filter = boundary_check(self.tph_sett.filter, 0, 7)?;
reg_addr = 0x75u8;
let mut data = self.get_regs_u8(reg_addr)?;
// TODO duplicate check of condition ?
if desired_settings.contains(DesiredSensorSettings::FILTER_SEL) {
data = (data as (i32) & !0x1ci32 |tph_sett_filter as (i32) << 2i32 & 0x1ci32)
as (u8);
}
reg.push((reg_addr, data));
}
if desired_settings.contains(DesiredSensorSettings::HCNTRL_SEL) {
let gas_sett_heatr_ctrl = boundary_check(self.gas_sett.heatr_ctrl, 0x0u8, 0x8u8)?;
reg_addr = 0x70u8;
let mut data = self.get_regs_u8(reg_addr)?;
data = (data as (i32) & !0x8i32 | gas_sett_heatr_ctrl as (i32) & 0x8) as (u8) ;
reg.push((reg_addr, data));
}
/* Selecting heater T,P oversampling for the sensor */
if desired_settings
.contains(DesiredSensorSettings::OST_SEL | DesiredSensorSettings::OSP_SEL)
{
reg_addr = 0x74u8;
let mut data = self.get_regs_u8(reg_addr)?;
if desired_settings.contains(DesiredSensorSettings::OST_SEL) {
let tph_sett_os_temp = boundary_check(self.tph_sett.os_temp, 0, 5)?;
data = (data as (i32) & !0xe0i32 | tph_sett_os_temp as (i32) << 5i32 & 0xe0i32)
as (u8);
}
if desired_settings.contains(DesiredSensorSettings::OSP_SEL) {
let tph_sett_os_pres = self.tph_sett.os_temp.ok_or(Bme680Error::NulltPtr)?;
data = (data as (i32) & !0x1ci32 | tph_sett_os_pres as (i32) << 2i32 & 0x1ci32)
as (u8);
}
reg.push((reg_addr, data));
}
/* Selecting humidity oversampling for the sensor */
if desired_settings.contains(DesiredSensorSettings::OSH_SEL) {
let tph_sett_os_hum = boundary_check(self.tph_sett.os_hum, 0, 5)?;
reg_addr = 0x72u8;
let mut data = self.get_regs_u8(reg_addr)?;
data = (data as (i32) & !0x7i32 | tph_sett_os_hum as (i32) & 0x7i32) as (u8);
reg.push((reg_addr, data));
}
/* Selecting the runGas and NB conversion settings for the sensor */
if desired_settings
.contains(DesiredSensorSettings::RUN_GAS_SEL | DesiredSensorSettings::NBCONV_SEL)
{
reg_addr = 0x71u8;
let mut data = self.get_regs_u8(reg_addr)?;
if desired_settings.contains(DesiredSensorSettings::RUN_GAS_SEL) {
let gas_sett_run_gas = boundary_check(self.gas_sett.run_gas, 0, 1)?;
data = (data as (i32) & !0x10i32 | gas_sett_run_gas as (i32) << 4i32 & 0x10i32)
as (u8);
}
if desired_settings.contains(DesiredSensorSettings::NBCONV_SEL) {
let gas_sett_nb_conv = boundary_check(self.gas_sett.nb_conv, 0, 10)?;
data = (data as (i32) & !0xfi32 | gas_sett_nb_conv as (i32) & 0xfi32) as (u8);
}
reg.push((reg_addr, data));
}
self.bme680_set_regs(reg.as_slice())?;
/* Restore previous intended power mode */
self.power_mode = intended_power_mode;
Ok(())
}
// TODO replace desired_settings with proper flags type see lib.rs
pub fn get_sensor_settings(&mut self, desired_settings: u16) -> Result<SensorSettings> {
let reg_addr: u8 = 0x70u8;
let mut data_array: [u8; BME680_REG_BUFFER_LENGTH] = [0; BME680_REG_BUFFER_LENGTH];
let mut sensor_settings: SensorSettings = Default::default();
self.i2c.read(reg_addr, &mut data_array).map_err(|_| Bme680Error::CommunicationFailure)?;
if desired_settings & BME680_GAS_MEAS_SEL != 0 {
sensor_settings.gas_sett = self.get_gas_config()?;
}
if desired_settings & BME680_FILTER_SEL != 0 {
sensor_settings.tph_sett.filter =
Some(((data_array[5usize] as (i32) & 0x1ci32) >> 2i32) as (u8));
}
if desired_settings & (BME680_OST_SEL | BME680_OSP_SEL) != 0 {
sensor_settings.tph_sett.os_temp =
Some(((data_array[4usize] as (i32) & 0xe0i32) >> 5i32) as (u8));
sensor_settings.tph_sett.os_pres =
Some(((data_array[4usize] as (i32) & 0x1ci32) >> 2i32) as (u8));
}
if desired_settings & BME680_OSH_SEL != 0 {
sensor_settings.tph_sett.os_hum = Some((data_array[2usize] as (i32) & 0x7i32) as (u8));
}
if desired_settings & BME680_HCNTRL_SEL != 0 {
sensor_settings.gas_sett.heatr_ctrl = Some((data_array[0usize] as (i32) & 0x8i32) as (u8));
}
if desired_settings & (BME680_RUN_GAS_SEL | BME680_NBCONV_SEL) != 0 {
sensor_settings.gas_sett.nb_conv = Some((data_array[1usize] as (i32) & 0xfi32) as (u8));
sensor_settings.gas_sett.run_gas =
Some(((data_array[1usize] as (i32) & 0x10i32) >> 4i32) as (u8));
}
Ok(sensor_settings)
}
pub fn bme680_set_sensor_mode(&mut self, target_power_mode: PowerMode) -> Result<()> {
let mut tmp_pow_mode: u8;
let mut current_power_mode: PowerMode;
let reg_addr: u8 = 0x74u8;
/* Call repeatedly until in sleep */
loop {
tmp_pow_mode = self.get_regs_u8(BME680_CONF_T_P_MODE_ADDR)?;
/* Put to sleep before changing mode */
current_power_mode = PowerMode::from(tmp_pow_mode & BME680_MODE_MSK);
if current_power_mode != PowerMode::SleepMode {
/* Set to sleep*/
tmp_pow_mode = tmp_pow_mode & !BME680_MODE_MSK;
let reg = vec!((reg_addr, tmp_pow_mode));
self.bme680_set_regs(reg.as_slice())?;
self.delay.delay_ms(BME680_POLL_PERIOD_MS);
} else {
// TODO do while in Rust?
break;
}
}
/* Already in sleep */
if current_power_mode != PowerMode::SleepMode {
tmp_pow_mode = tmp_pow_mode & !BME680_MODE_MSK | target_power_mode.value();
self.bme680_set_regs(&[(reg_addr, tmp_pow_mode)])?;
}
Ok(())
}
pub fn get_sensor_mode(&mut self) -> Result<PowerMode> {
let regs = self.get_regs_u8(BME680_CONF_T_P_MODE_ADDR)?;
let mode = regs & BME680_MODE_MSK;
Ok(PowerMode::from(mode))
}
pub fn bme680_set_profile_dur(&mut self, tph_sett: TphSett, duration: u16) {
let os_to_meas_cycles: [u8; 6] = [0u8, 1u8, 2u8, 4u8, 8u8, 16u8];
// TODO check if the following unwrap_ors do not change behaviour
let mut meas_cycles = os_to_meas_cycles[tph_sett.os_temp.unwrap_or(0) as (usize)] as (u32);
meas_cycles =
meas_cycles.wrapping_add(os_to_meas_cycles[tph_sett.os_pres.unwrap_or(0) as (usize)] as (u32));
meas_cycles =
meas_cycles.wrapping_add(os_to_meas_cycles[tph_sett.os_hum.unwrap_or(0) as (usize)] as (u32));
let mut tph_dur = meas_cycles.wrapping_mul(1963u32);
tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(4u32));
tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(5u32));
tph_dur = tph_dur.wrapping_add(500u32);
tph_dur = tph_dur.wrapping_div(1000u32);
tph_dur = tph_dur.wrapping_add(1u32);
self.gas_sett.heatr_dur = Some((duration as (i32) - tph_dur as (u16) as (i32)) as (u16));
}
pub fn get_profile_dur(&self, tph_sett: TphSett, gas_sett: GasSett) -> Result<u16> {
let os_to_meas_cycles: [u8; 6] = [0u8, 1u8, 2u8, 4u8, 8u8, 16u8];
// TODO check if the following unwrap_ors do not change behaviour
let mut meas_cycles = os_to_meas_cycles[tph_sett.os_temp.unwrap_or(0) as (usize)] as (u32);
meas_cycles =
meas_cycles.wrapping_add(os_to_meas_cycles[tph_sett.os_pres.unwrap_or(0) as (usize)] as (u32));
meas_cycles =
meas_cycles.wrapping_add(os_to_meas_cycles[tph_sett.os_hum.unwrap_or(0) as (usize)] as (u32));
let mut tph_dur = meas_cycles.wrapping_mul(1963u32);
tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(4u32));
tph_dur = tph_dur.wrapping_add(477u32.wrapping_mul(5u32));
tph_dur = tph_dur.wrapping_add(500u32);
tph_dur = tph_dur.wrapping_div(1000u32);
tph_dur = tph_dur.wrapping_add(1u32);
let mut duration = tph_dur as (u16);
if gas_sett.run_gas.unwrap_or(0) != 0 {
duration = duration + gas_sett.heatr_dur.ok_or(Bme680Error::NulltPtr)?;
}
Ok(duration)
}
/// @returns (FieldData, IsNewFields)
pub fn get_sensor_data(&mut self) -> Result<(FieldData, FieldDataState)> {
let field_data = self.read_field_data()?;
if field_data.status & BME680_NEW_DATA_MSK != 0 {
// new fields
Ok((field_data, FieldDataState::NewData))
} else {
Ok((field_data, FieldDataState::NoNewData))
}
}
fn get_calib_data(&mut self) -> Result<CalibData> {
let mut calib: CalibData = Default::default();
let mut coeff_array: [u8; BME680_COEFF_SIZE] = [0; BME680_COEFF_SIZE];
self.i2c.read(
BME680_COEFF_ADDR1,
&mut coeff_array,
).map_err(|_| Bme680Error::CommunicationFailure)?;
self.i2c.read(
BME680_COEFF_ADDR2,
&mut coeff_array,
).map_err(|_| Bme680Error::CommunicationFailure)?;
calib.par_t1 = (coeff_array[34usize] as (u16) as (i32) << 8i32
| coeff_array[33usize] as (u16) as (i32)) as (u16);
calib.par_t2 = (coeff_array[2usize] as (u16) as (i32) << 8i32
| coeff_array[1usize] as (u16) as (i32)) as (i16);
calib.par_t3 = coeff_array[3usize] as (i8);
calib.par_p1 = (coeff_array[6usize] as (u16) as (i32) << 8i32
| coeff_array[5usize] as (u16) as (i32)) as (u16);
calib.par_p2 = (coeff_array[8usize] as (u16) as (i32) << 8i32
| coeff_array[7usize] as (u16) as (i32)) as (i16);
calib.par_p3 = coeff_array[9usize] as (i8);
calib.par_p4 = (coeff_array[12usize] as (u16) as (i32) << 8i32
| coeff_array[11usize] as (u16) as (i32)) as (i16);
calib.par_p5 = (coeff_array[14usize] as (u16) as (i32) << 8i32
| coeff_array[13usize] as (u16) as (i32)) as (i16);
calib.par_p6 = coeff_array[16usize] as (i8);
calib.par_p7 = coeff_array[15usize] as (i8);
calib.par_p8 = (coeff_array[20usize] as (u16) as (i32) << 8i32
| coeff_array[19usize] as (u16) as (i32)) as (i16);
calib.par_p9 = (coeff_array[22usize] as (u16) as (i32) << 8i32
| coeff_array[21usize] as (u16) as (i32)) as (i16);
calib.par_p10 = coeff_array[23usize];
calib.par_h1 = (coeff_array[27usize] as (u16) as (i32) << 4i32
| coeff_array[26usize] as (i32) & 0xfi32) as (u16);
calib.par_h2 = (coeff_array[25usize] as (u16) as (i32) << 4i32
| coeff_array[26usize] as (i32) >> 4i32) as (u16);
calib.par_h3 = coeff_array[28usize] as (i8);
calib.par_h4 = coeff_array[29usize] as (i8);
calib.par_h5 = coeff_array[30usize] as (i8);
calib.par_h6 = coeff_array[31usize];
calib.par_h7 = coeff_array[32usize] as (i8);
calib.par_gh1 = coeff_array[37usize] as (i8);
calib.par_gh2 = (coeff_array[36usize] as (u16) as (i32) << 8i32
| coeff_array[35usize] as (u16) as (i32)) as (i16);
calib.par_gh3 = coeff_array[38usize] as (i8);
calib.res_heat_range = (self.get_regs_u8(BME680_ADDR_RES_HEAT_RANGE_ADDR)? & 0x30) / 16;
calib.res_heat_val = self.get_regs_i8(BME680_ADDR_RES_HEAT_VAL_ADDR)?;
calib.range_sw_err = (self.get_regs_u8(BME680_ADDR_RANGE_SW_ERR_ADDR)? & BME680_RSERROR_MSK) / 16;
Ok(calib)
}
fn set_gas_config(&mut self, gas_sett: GasSett) -> Result<()> {
let mut reg = Vec::with_capacity(2);
if self.power_mode != PowerMode::ForcedMode {
return Err(Bme680Error::DefinePwrMode);
}
// TODO check whether unwrap_or changes behaviour
reg.push((BME680_RES_HEAT0_ADDR, self.calc_heater_res(gas_sett.heatr_temp.unwrap_or(0))));
reg.push((BME680_GAS_WAIT0_ADDR, self.calc_heater_dur(gas_sett.heatr_dur.unwrap_or(0))));
self.gas_sett.nb_conv = Some(0);
self.bme680_set_regs(reg.as_slice())
}
fn get_gas_config(&mut self) -> Result<GasSett> {
// TODO move both GasSett fields to new struct
let mut gas_sett: GasSett = Default::default();
// TODO figure out if heat_temp and dur can be u8
gas_sett.heatr_temp = Some(self.get_regs_u8(BME680_ADDR_SENS_CONF_START)? as u16);
gas_sett.heatr_dur = Some(self.get_regs_u8(BME680_ADDR_GAS_CONF_START)? as u16);
Ok(gas_sett)
}
fn calc_heater_res(&self, temp: u16) -> u8 {
// cap temperature
let temp = if temp <= 400 { temp } else { 400 };
let var1 = self.amb_temp as (i32) * self.calib.par_gh3 as (i32) / 1000i32 * 256i32;
let var2 = (self.calib.par_gh1 as (i32) + 784i32)
* (((self.calib.par_gh2 as (i32) + 154009i32) * temp as (i32) * 5i32 / 100i32
+ 3276800i32) / 10i32);
let var3 = var1 + var2 / 2i32;
let var4 = var3 / (self.calib.res_heat_range as (i32) + 4i32);
let var5 = 131i32 * self.calib.res_heat_val as (i32) + 65536i32;
let heatr_res_x100 = (var4 / var5 - 250i32) * 34i32;
((heatr_res_x100 + 50i32) / 100i32) as (u8)
}
fn calc_heater_dur(&self, dur: u16) -> u8 {
let mut factor: u8 = 0u8;
let mut dur = dur;
let durval =
if dur as (i32) >= 0xfc0i32 {
0xffu8 // Max duration
} else {
loop {
if !(dur as (i32) > 0x3fi32) {
break;
}
dur = (dur as (i32) / 4i32) as (u16);
factor = (factor as (i32) + 1i32) as (u8);
}
(dur as (i32) + factor as (i32) * 64i32) as (u8)
};
durval
}
fn calc_temperature(&mut self, temp_adc: u32) -> i16 {
let var1 = ((temp_adc as (i32) >> 3i32) - (self.calib.par_t1 as (i32) << 1i32)) as (isize);
let var2 = var1 * self.calib.par_t2 as (i32) as (isize) >> 11i32;
let var3 = (var1 >> 1i32) * (var1 >> 1i32) >> 12i32;
let var3 = var3 * (self.calib.par_t3 as (i32) << 4i32) as (isize) >> 14i32;
// TODO really assign here ?
self.calib.t_fine = (var2 + var3) as (i32);
let calc_temp = (self.calib.t_fine * 5i32 + 128i32 >> 8i32) as (i16);
calc_temp
}
fn calc_pressure(&self, pres_adc: u32) -> u32 {
let mut var1 = (self.calib.t_fine >> 1i32) - 64000i32;
let mut var2 = ((var1 >> 2i32) * (var1 >> 2i32) >> 11i32) * self.calib.par_p6 as (i32) >> 2i32;
var2 = var2 + (var1 * self.calib.par_p5 as (i32) << 1i32);
var2 = (var2 >> 2i32) + (self.calib.par_p4 as (i32) << 16i32);
var1 = (((var1 >> 2i32) * (var1 >> 2i32) >> 13i32) * (self.calib.par_p3 as (i32) << 5i32)
>> 3i32) + (self.calib.par_p2 as (i32) * var1 >> 1i32);
var1 = var1 >> 18i32;
var1 = (32768i32 + var1) * self.calib.par_p1 as (i32) >> 15i32;
let mut pressure_comp = 1048576u32.wrapping_sub(pres_adc) as (i32);
pressure_comp = ((pressure_comp - (var2 >> 12i32)) as (u32)).wrapping_mul(3125u32) as (i32);
if pressure_comp >= 0x40000000i32 {
pressure_comp = ((pressure_comp as (u32)).wrapping_div(var1 as (u32)) << 1i32) as (i32);
} else {
pressure_comp = ((pressure_comp << 1i32) as (u32)).wrapping_div(var1 as (u32)) as (i32);
}
var1 = self.calib.par_p9 as (i32)
* ((pressure_comp >> 3i32) * (pressure_comp >> 3i32) >> 13i32) >> 12i32;
var2 = (pressure_comp >> 2i32) * self.calib.par_p8 as (i32) >> 13i32;
let var3 = (pressure_comp >> 8i32) * (pressure_comp >> 8i32) * (pressure_comp >> 8i32)
* self.calib.par_p10 as (i32) >> 17i32;
pressure_comp =
pressure_comp + (var1 + var2 + var3 + (self.calib.par_p7 as (i32) << 7i32) >> 4i32);
pressure_comp as (u32)
}
fn calc_humidity(&self, hum_adc: u16) -> u32 {
let temp_scaled = self.calib.t_fine * 5i32 + 128i32 >> 8i32;
let var1 = hum_adc as (i32) - self.calib.par_h1 as (i32) * 16i32
- (temp_scaled * self.calib.par_h3 as (i32) / 100i32 >> 1i32);
let var2 = self.calib.par_h2 as (i32)
* (temp_scaled * self.calib.par_h4 as (i32) / 100i32
+ (temp_scaled * (temp_scaled * self.calib.par_h5 as (i32) / 100i32) >> 6i32)
/ 100i32 + (1i32 << 14i32)) >> 10i32;
let var3 = var1 * var2;
let var4 = self.calib.par_h6 as (i32) << 7i32;
let var4 = var4 + temp_scaled * self.calib.par_h7 as (i32) / 100i32 >> 4i32;
let var5 = (var3 >> 14i32) * (var3 >> 14i32) >> 10i32;
let var6 = var4 * var5 >> 1i32;
let mut calc_hum = (var3 + var6 >> 10i32) * 1000i32 >> 12i32;
if calc_hum > 100000i32 {
calc_hum = 100000i32;
} else if calc_hum < 0i32 {
calc_hum = 0i32;
}
calc_hum as (u32)
}
fn calc_gas_resistance(&mut self, gas_res_adc: u16, gas_range: u8) -> u32 {
let lookup_table1: [u32; 16] = [
2147483647u32,
2147483647u32,
2147483647u32,
2147483647u32,
2147483647u32,
2126008810u32,
2147483647u32,
2130303777u32,
2147483647u32,
2147483647u32,
2143188679u32,
2136746228u32,
2147483647u32,
2126008810u32,
2147483647u32,
2147483647u32,
];
let lookup_table2: [u32; 16] = [
4096000000u32,
2048000000u32,
1024000000u32,
512000000u32,
255744255u32,
127110228u32,
64000000u32,
32258064u32,
16016016u32,
8000000u32,
4000000u32,
2000000u32,
1,
500000u32,
250000u32,
125000u32,
];
let var1 = (1340isize + 5isize * self.calib.range_sw_err as (isize))
* lookup_table1[gas_range as (usize)] as (isize) >> 16i32;
let var2 = ((gas_res_adc as (isize) << 15i32) - 16777216isize + var1) as (usize);
let var3 = lookup_table2[gas_range as (usize)] as (isize) * var1 >> 9i32;
let calc_gas_res = ((var3 + (var2 as (isize) >> 1i32)) / var2 as (isize)) as (u32);
calc_gas_res
}
fn read_field_data(&mut self) -> Result<FieldData> {
let mut buff = [0, BME680_FIELD_LENGTH];
let mut data: FieldData = Default::default();
let mut gas_range: u8;
let mut adc_temp: u32;
let mut adc_pres: u32;
let mut adc_hum: u16;
let mut adc_gas_res: u16;
let mut tries: u8 = 10u8;
loop {
self.i2c.read(BME680_FIELD0_ADDR, &mut buff)
.map_err(|_| Bme680Error::CommunicationFailure)?;
data.status = buff[0] & BME680_NEW_DATA_MSK;
data.gas_index = buff[0] & BME680_GAS_INDEX_MSK;;
data.meas_index = buff[1];
adc_pres = (buff[2] as (u32)).wrapping_mul(4096) | (buff[3] as (u32)).wrapping_mul(16)
| (buff[4] as (u32)).wrapping_div(16);
adc_temp = (buff[5] as (u32)).wrapping_mul(4096) | (buff[6] as (u32)).wrapping_mul(16)
| (buff[7] as (u32)).wrapping_div(16);
adc_hum = ((buff[8] as (u32)).wrapping_mul(256) | buff[9] as (u32)) as (u16);
adc_gas_res = ((buff[13] as (u32)).wrapping_mul(4)
| (buff[14] as (u32)).wrapping_div(64)) as (u16);
gas_range = buff[14] & BME680_GAS_RANGE_MSK;
data.status = data.status | buff[14] & BME680_GASM_VALID_MSK;
data.status = data.status | buff[14] & BME680_HEAT_STAB_MSK;
if data.status & BME680_NEW_DATA_MSK != 0 {
data.temperature = self.calc_temperature(adc_temp);
data.pressure = self.calc_pressure(adc_pres);
data.humidity = self.calc_humidity(adc_hum);
data.gas_resistance = self.calc_gas_resistance(adc_gas_res, gas_range);
return Ok(data);
}
self.delay.delay_ms(BME680_POLL_PERIOD_MS);
tries = tries - 1;
if tries == 0 {
break;
}
}
Err(Bme680Error::NoNewData)
}
}