Remove old files
This commit is contained in:
parent
c858e4de91
commit
e17260a5fc
7 changed files with 846 additions and 1789 deletions
368
Cargo.lock
generated
368
Cargo.lock
generated
|
@ -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"
|
|
||||||
|
|
|
@ -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"
|
|
||||||
|
|
34
build.rs
34
build.rs
|
@ -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!");
|
|
||||||
}
|
|
907
src/bme680.rs
907
src/bme680.rs
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
|
@ -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 }
|
|
||||||
}
|
|
||||||
}
|
|
887
src/lib.rs
887
src/lib.rs
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue