Add support for reading and writing to I2C devices from lua#934
Add support for reading and writing to I2C devices from lua#934d0k3 merged 15 commits intod0k3:masterfrom
Conversation
With memory permissions before write
In this case I think it should not return anything, and raise an error if it fails. Or if there is a reason to return a specific value, then return that. |
|
Since malicious or negligent i2c writes have the potential to cause bricks, I think an unlock mechanism that makes the user aware that the script is about to write to i2c would be pretty important to have. |
|
Writing now returns nothing (nil) on a success or lua error on fail |
|
The write function should use a list of registers allowed to write to (list below provided by Wolfvak). Unless GM9 has this already enforced somewhere else that I'm not aware of. 0x15-0x17, 0x1c-0x1f, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d |
|
A whitelist is now implemented, as well as some register constants and bitmasks/values for some of the registers. Test scriptprint("Hello World!")
print(CONSOLE_TYPE)
-- device 3 is the mcu
-- 0x09 is volume slider
ui.echo(i2c.read(3, 0x09, 1)[1])
-- Read voltage from MCU device
local voltage_raw = i2c.read(i2c.dev.MCU, i2c.mcu.reg.BATTERY_VOLTAGE, 1)
local voltage = voltage_raw[1] * 5 / 256.0
print("System voltage:", voltage, "V")
-- Read Power status
local power_state = i2c.read(i2c.dev.MCU, i2c.mcu.reg.POWER_STATUS, 1)
print("power_state: ", power_state[1])
print("Power status flags:", i2c.mcu.power_status_flags.SHELL_OPEN, " - ", i2c.mcu.power_status_flags.CHARGING)
if power_state[1] & i2c.mcu.power_status_flags.SHELL_OPEN ~= 0 then
print("Shell is open")
end
if power_state[1] & i2c.mcu.power_status_flags.CHARGING ~= 0 then
print("Charging")
end
-- 0x28 is Brightness of the WiFi/Power LED
ui.echo("Reg: "..i2c.read(3, 0x28, 1)[1])
i2c.write(3, 0x28, {200})
ui.echo("Reg: "..i2c.read(3, 0x28, 1)[1])
i2c.write(3, 0x28, {150})
ui.echo("Reg: "..i2c.read(3, 0x28, 1)[1])
i2c.write(3, 0x28, {70})
ui.echo("Reg: "..i2c.read(3, 0x28, 1)[1])
-- 0x15-17 is not in use
local data = i2c.read(3, 0x15, 3)
ui.echo(string.format("Reg: %d, %d, %d", data[1], data[2], data[3]))
i2c.write(3, 0x15, {20, 30, 40})
data = i2c.read(3, 0x15, 3)
ui.echo(string.format("Reg: %d, %d, %d", data[1], data[2], data[3]))
-- Test write outside of the range:
ui.echo("Reg 36: "..i2c.read(3, 0x36, 1)[1])
ui.echo("Attempting to write to reg 36, which is outside of the allowed range...")
i2c.write(3, 0x36, {0})
ui.echo("Reg 36: "..i2c.read(3, 0x36, 1)[1])This correctly reports that the shell is open, and if it is charging or not. |
|
Merged, thanks a lot for your contribution! I also like the testing script. |
This is essentially just a wrapper for the exisiting C functions.
Writing is currently set to require PERM_MEMORY
I have tested this a bit, and it seems to work ok
The syntax is
i2c.read(device_id, register, length)andi2c.write(device_id, register, data_table)Reading returns a table of values, while writing returns a bool True on success or errors on a fail.
(Should this return a false and a string instead of error?)
Test script
Volume slider reads fine, voltage reads back 3.68 (seems ok), I don't see any LED stuff, but when reading back the same register I see the changes. The final test is reading and writing multiple registers, this also seems to work ok.