-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
In an effort to decrease the project's technical debt, I've proposed (in #3124) that the C-only bme280
be cut into a Lua layer that drives communication and a C module that does any requisite low-level fiddling. This will be similar to #2819 and may, incidentally, address #2527 correctly as well. (As you can see, between that and #2241, this module has a history of being sufficiently troublesome that issues have been worked around rather than fixed.) This rewrite will also eliminate yet another source of static allocation and artificial limitation in our driver layer. All in all, deeply worth it.
I would like it very much if the result of this rewrite included a test driver, as well. Ideally bme280
becomes an example of how all drivers should look. No pressure (ha!). ;)
OK, so, what does this entail, concretely?
Looking at the existing bme280.c
, we almost immediately see that there's a bunch of goo associated with performing i2c
transactions: bme280_i2c_addr
, r8u_n
, r8u
, and w8u
. These can all be directly transcoded to Lua. The results from the i2c
package will be Lua strings.
The bme280_data
structure holds per-device state obtained during setup
, which means we probably want to hold it instead in a Lua userdata object that represents the sensor. Reading setup
, it looks like this takes 3 or 4 I2C transactions to set up, including getting the chip ID, so I think our sensor object constructor should take 2 or 3 Lua strings (DIG_T
, DIG_P
, and DIG_H
) to build itself. Since it appears that the static values bme280_t_fine
, bme280_h
, and bme280_hc
may outlive a particular measurement, they should perhaps join the bme280_data
in the per-device userdata object.
Armed with the sensor parameters, we can look at interacting with the device: bme280_lua_startreadout
does some i2c transactions, easily done instead in Lua, and schedules a timer, also easily done in Lua. (Can the device not raise IRQs?)
Once it's time to read data, bme280_lua_read
does some more i2c transactions and a lot of math, including storing "fine" constants between procedure calls. To continue the theme, the transactions should be done in Lua, and passed to a C routine that takes the sensor userdata object and does the requisite math. For my $0.02, the results should just land in a Lua table.
The abbreviated bme280_lua_temp
, bme280_lua_baro
, and bme280_lua_humi
functions are readily achieved by having the Lua replacement for bme280_lua_read
perform fewer transactions and call into the C function with fewer string arguments. That function should return a table with fewer keys as a result.
For the purposes of PRing, I'd suggest placing code in
app/modules/bme280_math.c
for the C layerlua_modules/bme280/bme280.lua
for the Lua top-level and main driverlua_modules/bme280/bme280_test.lua
for the test script (ideally in mispec, I think? See Create unit tests in Lua #2145).