You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
2.4 KiB
Go

// package i2c wraps the [i2c package] to interact with the i2c
// with devices on the bus
//
// [i2c package]: https://pkg.go.dev/periph.io/x/conn/v3/i2c#pkg-overview
2 years ago
package i2c
3 years ago
import (
"FRMS/internal/pkg/logging"
"bytes"
"fmt"
_ "log"
"os/exec"
"strconv"
"strings"
)
3 years ago
// GetConnected returns a map of each device address and its current
// connection status.
2 years ago
func GetConnected(b int) (map[int]bool, error) {
2 years ago
bus := strconv.Itoa(b)
devices := make(map[int]bool) // only keys
cmd := exec.Command("i2cdetect", "-y", "-r", bus)
var out bytes.Buffer
var errs bytes.Buffer
cmd.Stderr = &errs
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
logging.Debug(
logging.DError,
"I2C scan error %v",
errs.String(),
)
return devices, err
}
// parsing the command output
outString := out.String()
split := strings.SplitAfter(outString, ":")
// 1st entry is reserved and ending is always \n##:
split = split[1:]
// create empty slice for all the devices
for i, v := range split {
lastDevice := strings.Index(v, "\n")
trimmed := v[:lastDevice]
trimmed = strings.Trim(trimmed, " ")
count := strings.Split(trimmed, " ")
for j, d := range count {
// the first row has to be offset by 3 but after its just i*16 + j
offset := j
if i == 0 {
offset += 3
}
addr := i*16 + offset
if !strings.Contains(d, "--") && !strings.Contains(d, "UU") {
devices[addr] = true
}
}
}
return devices, nil
}
// SendCmd sends an arbitrary command string to the device at addr on i2c bus b.
// Command will be converted from a string to bytes before
// attempting to be sent.
2 years ago
func SendCmd(b, addr int, command string) (string, error) {
var cmd *exec.Cmd
2 years ago
bus := strconv.Itoa(b)
// default to an empty read
operation := "r20"
frmt_cmd := ""
if command != "" {
// command, do write
operation = fmt.Sprintf("w%d", len(command)) // write
// formatting cmd
for _, char := range command {
// loop over string
frmt_cmd += fmt.Sprintf("0x%x", char)
}
cmd = exec.Command("i2ctransfer", "-y", bus, fmt.Sprintf("%s@0x%x", operation, addr), frmt_cmd)
} else {
// reading
cmd = exec.Command("i2ctransfer", "-y", bus, fmt.Sprintf("%s@0x%x", operation, addr))
}
// execute command
var out bytes.Buffer
var errs bytes.Buffer
cmd.Stderr = &errs
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
logging.Debug(logging.DError, "I2C command error %v", err)
return "", err
}
2 years ago
return out.String(), nil
}