Files
LoraSA/lib/comms/bus.cpp
2025-04-11 07:15:53 +01:00

235 lines
6.0 KiB
C++

#include "bus.h"
bool initUARTs(Config &config)
{
if (config.uart0.enabled)
{
Uart0.end();
Uart0.begin(config.uart0.clock_freq, SERIAL_8N1, config.uart0.rx,
config.uart0.tx);
}
if (config.uart1.enabled)
{
Uart1.end();
Uart1.begin(config.uart1.clock_freq, SERIAL_8N1, config.uart1.rx,
config.uart1.tx);
}
return true;
}
#ifndef HELTEC
SPIClass &hspi = *(new SPIClass(HSPI)); // not usable until initSPIs
#endif
bool initSPIs(Config &config)
{
if (config.spi1.enabled)
{
#ifndef HELTEC
delete (&hspi);
hspi = *(new SPIClass(config.spi1.bus_num));
if (config.spi1.clock_freq > 0)
{
hspi.setFrequency(config.spi1.clock_freq);
}
// if all the pins are -1, then will use the default for SPI bus_num
hspi.begin(config.spi1.clk, config.spi1.miso, config.spi1.mosi);
Serial.printf("Initialized SPI%d @ %x: SC:%d MISO:%d MOSI:%d clock:%d\n",
(int)config.spi1.bus_num, (void *)&hspi, (int)config.spi1.clk,
(int)config.spi1.miso, (int)config.spi1.mosi,
(int)config.spi1.clock_freq);
#else
Serial.println("Custom SPI initializer not supported on Heltec");
#endif
}
return true;
}
uint8_t _scanSupportedDevicesOnWire(TwoWire &w, int bus_num);
uint8_t wireDevices;
uint8_t wire1Devices;
bool initWires(Config &config)
{
wireDevices = _scanSupportedDevicesOnWire(Wire, 0);
if (config.wire1.enabled)
{
#if SOC_I2C_NUM > 1
// if you want to use default pins, configure -1
// if you want to use default clock speed, configure 0
if (!Wire1.begin(config.wire1.sda, config.wire1.scl, config.wire1.clock_freq))
{
Serial.println("Failed to initialize Wire1");
return false;
}
wire1Devices = _scanSupportedDevicesOnWire(Wire1, 1);
#endif
}
return true;
}
uint8_t _scanSupportedDevicesOnWire(TwoWire &w, int bus_num)
{
uint8_t res = 0;
for (int i = 0; known_i2c_devices[i].address > 0; i++)
{
w.beginTransmission(known_i2c_devices[i].address);
delay(2);
if (w.endTransmission() == 0)
{
Serial.printf("Found supported device on Wire%d: %s(%X)\n", bus_num,
known_i2c_devices[i].name.c_str(),
(int)known_i2c_devices[i].address);
res |= 1 << i;
}
}
return res;
}
uint8_t _write_register(TwoWire &wire, uint8_t addr, uint8_t reg, uint8_t value,
bool skipValue)
{
wire.beginTransmission(addr);
size_t s = wire.write(reg);
if (s == 1 && !skipValue)
{
s = wire.write(value);
}
size_t s1 = wire.endTransmission();
if (s != 1 && s1 == 0)
{
return 1; // "data too long to fit in transmit buffer"
}
return s1;
}
uint8_t _write_registers(TwoWire &wire, uint8_t addr, uint8_t reg, size_t sz,
const uint8_t *value)
{
wire.beginTransmission(addr);
size_t s = wire.write(reg);
if (s == 1 && sz > 0)
{
s = wire.write(value, sz);
}
size_t s1 = wire.endTransmission();
if (s != sz && s1 == 0)
{
return 1; // "data too long to fit in transmit buffer"
}
return s1;
}
int8_t I2Cdev::writeBytes(TwoWire &w, uint8_t addr, uint8_t reg, size_t sz,
const uint8_t *buf)
{
return _write_registers(w, addr, reg, sz, buf);
}
int8_t I2Cdev::writeWords(TwoWire &w, uint8_t addr, uint8_t reg, size_t sz,
const uint16_t *buf16)
{
uint8_t *buf = (uint8_t *)malloc(sz * 2);
uint8_t *p = buf;
for (int i = 0; i < sz; i++)
{
*(p++) = buf16[i] >> 8;
*(p++) = (uint8_t)buf16[i];
}
uint8_t r = writeBytes(w, addr, reg, sz * 2, buf);
free(buf);
return r;
}
int8_t I2Cdev::writeBit(TwoWire &wireObj, uint8_t addr, uint8_t reg, size_t bitNum,
uint8_t data)
{
uint8_t b;
int8_t r = readBytes(wireObj, addr, reg, 1, &b, I2Cdev::readTimeout);
if (r != 1)
{
return r;
}
b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
return writeBytes(wireObj, addr, reg, 1, &b);
}
int8_t I2Cdev::writeBits(TwoWire &w, uint8_t addr, uint8_t reg, size_t bitn, size_t sz,
uint8_t v)
{
// 010 value to write
// 76543210 bit numbers
// xxx args: bitn=4, sz=3
// 00011100 mask byte
// 10101111 original value (sample)
// 10100011 original & ~mask
// 10101011 masked | value
uint8_t b;
int8_t r = readBytes(w, addr, reg, 1, &b, I2Cdev::readTimeout);
if (r != 1)
{
return r;
}
uint8_t mask = ((1 << sz) - 1) << (bitn - sz + 1);
v <<= (bitn - sz + 1); // shift data into correct position
v &= mask; // zero all non-important bits in data
b &= ~(mask); // zero all important bits in existing byte
b |= v; // combine data with existing byte
return writeBytes(w, addr, reg, 1, &b);
}
int8_t _read_registers(TwoWire &wire, uint8_t addr, uint8_t reg, uint8_t *v, size_t sz,
bool skipRegister)
{
if (!skipRegister)
{
uint8_t s = _write_registers(wire, addr, reg, 0, NULL);
if (s != 0)
{
return s;
}
}
uint8_t r = wire.requestFrom(addr, sz);
r = wire.readBytes(v, r);
return r - sz;
}
uint8_t _read_register(TwoWire &wire, uint8_t addr, uint8_t reg, uint8_t &v,
bool skipRegister)
{
uint8_t r = _read_registers(wire, addr, reg, &v, 1, skipRegister);
if (r != 0)
{
return 1;
}
return 0;
}
int8_t I2Cdev::readBytes(TwoWire &wireObj, uint8_t addr, uint8_t reg, size_t length,
uint8_t *data, uint16_t timeout)
{ // timeout is unused right now
return _read_registers(wireObj, addr, reg, data, length);
}
uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT;