2020-10-20 19:41:31 -03:00
|
|
|
#include "SIM_I2CDevice.h"
|
2020-11-12 04:43:29 -04:00
|
|
|
#include <AP_HAL/utility/sparse-endian.h>
|
2020-10-20 19:41:31 -03:00
|
|
|
|
|
|
|
void SITL::I2CRegisters::add_register(const char *name, uint8_t reg, int8_t mode)
|
|
|
|
{
|
|
|
|
// ::fprintf(stderr, "Adding register %u (0x%02x) (%s)\n", reg, reg, name);
|
|
|
|
regname[reg] = name;
|
|
|
|
if (mode == O_RDONLY || mode == O_RDWR) {
|
|
|
|
readable_registers.set((uint8_t)reg);
|
|
|
|
}
|
|
|
|
if (mode == O_WRONLY || mode == O_RDWR) {
|
|
|
|
writable_registers.set((uint8_t)reg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SITL::I2CRegisters_16Bit::set_register(uint8_t reg, uint16_t value)
|
|
|
|
{
|
|
|
|
if (regname[reg] == nullptr) {
|
|
|
|
AP_HAL::panic("Setting un-named register %u", reg);
|
|
|
|
}
|
|
|
|
// ::fprintf(stderr, "Setting %u (0x%02x) (%s) to 0x%02x (%c)\n", (unsigned)reg, (unsigned)reg, regname[reg], (unsigned)value, value);
|
|
|
|
word[reg] = htobe16(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SITL::I2CRegisters_16Bit::set_register(uint8_t reg, int16_t value)
|
|
|
|
{
|
|
|
|
if (regname[reg] == nullptr) {
|
|
|
|
AP_HAL::panic("Setting un-named register %u", reg);
|
|
|
|
}
|
|
|
|
// ::fprintf(stderr, "Setting %s (%u) to 0x%02x (%c)\n", regname[reg], (unsigned)reg, (signed)value, value);
|
|
|
|
word[reg] = htobe16(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
int SITL::I2CRegisters_16Bit::rdwr(I2C::i2c_rdwr_ioctl_data *&data)
|
|
|
|
{
|
|
|
|
if (data->nmsgs == 2) {
|
|
|
|
// data read request
|
|
|
|
if (data->msgs[0].flags != 0) {
|
|
|
|
AP_HAL::panic("Unexpected flags");
|
|
|
|
}
|
|
|
|
if (data->msgs[1].flags != I2C_M_RD) {
|
|
|
|
AP_HAL::panic("Unexpected flags");
|
|
|
|
}
|
|
|
|
const uint8_t reg_base_addr = data->msgs[0].buf[0];
|
|
|
|
uint8_t bytes_copied = 0;
|
|
|
|
while (bytes_copied < data->msgs[1].len) {
|
|
|
|
const uint8_t reg_addr = reg_base_addr + bytes_copied/2;
|
|
|
|
if (!readable_registers.get(reg_addr)) {
|
|
|
|
// ::printf("Register 0x%02x is not readable!\n", reg_addr);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
const uint16_t register_value = word[reg_addr];
|
|
|
|
data->msgs[1].buf[bytes_copied++] = register_value >> 8;
|
|
|
|
if (bytes_copied < data->msgs[1].len) {
|
|
|
|
data->msgs[1].buf[bytes_copied++] = register_value & 0xFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
data->msgs[1].len = bytes_copied;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data->nmsgs == 1) {
|
|
|
|
// data write request
|
|
|
|
if (data->msgs[0].flags != 0) {
|
|
|
|
AP_HAL::panic("Unexpected flags");
|
|
|
|
}
|
2020-11-12 00:18:50 -04:00
|
|
|
// FIXME: handle multi-register writes
|
2020-10-20 19:41:31 -03:00
|
|
|
const uint8_t reg_addr = data->msgs[0].buf[0];
|
|
|
|
if (!writable_registers.get(reg_addr)) {
|
|
|
|
AP_HAL::panic("Register 0x%02x is not writable!", reg_addr);
|
|
|
|
}
|
|
|
|
const uint16_t register_value = data->msgs[0].buf[2] << 8 | data->msgs[0].buf[1];
|
|
|
|
word[reg_addr] = register_value;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
};
|
2020-11-12 00:18:50 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2021-01-03 04:26:52 -04:00
|
|
|
void SITL::I2CRegisters_8Bit::set_register(uint8_t reg, uint8_t value)
|
|
|
|
{
|
|
|
|
if (regname[reg] == nullptr) {
|
|
|
|
AP_HAL::panic("Setting un-named register %u", reg);
|
|
|
|
}
|
|
|
|
// ::fprintf(stderr, "Setting %u (0x%02x) (%s) to 0x%02x (%c)\n", (unsigned)reg, (unsigned)reg, regname[reg], (unsigned)value, value);
|
|
|
|
byte[reg] = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SITL::I2CRegisters_8Bit::set_register(uint8_t reg, int8_t value)
|
|
|
|
{
|
|
|
|
if (regname[reg] == nullptr) {
|
|
|
|
AP_HAL::panic("Setting un-named register %u", reg);
|
|
|
|
}
|
|
|
|
// ::fprintf(stderr, "Setting %s (%u) to 0x%02x (%c)\n", regname[reg], (unsigned)reg, (signed)value, value);
|
|
|
|
byte[reg] = value;
|
|
|
|
}
|
|
|
|
|
2020-11-12 00:18:50 -04:00
|
|
|
int SITL::I2CRegisters_8Bit::rdwr(I2C::i2c_rdwr_ioctl_data *&data)
|
|
|
|
{
|
|
|
|
if (data->nmsgs == 2) {
|
|
|
|
// data read request
|
|
|
|
if (data->msgs[0].flags != 0) {
|
|
|
|
AP_HAL::panic("Unexpected flags");
|
|
|
|
}
|
|
|
|
if (data->msgs[1].flags != I2C_M_RD) {
|
|
|
|
AP_HAL::panic("Unexpected flags");
|
|
|
|
}
|
|
|
|
const uint8_t reg_base_addr = data->msgs[0].buf[0];
|
|
|
|
uint8_t bytes_copied = 0;
|
|
|
|
while (bytes_copied < data->msgs[1].len) {
|
|
|
|
const uint8_t reg_addr = reg_base_addr + bytes_copied;
|
|
|
|
if (!readable_registers.get(reg_addr)) {
|
|
|
|
// ::printf("Register 0x%02x is not readable!\n", reg_addr);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
const uint8_t register_value = byte[reg_addr];
|
|
|
|
data->msgs[1].buf[bytes_copied++] = register_value;
|
|
|
|
}
|
|
|
|
data->msgs[1].len = bytes_copied;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data->nmsgs == 1) {
|
|
|
|
// data write request
|
|
|
|
if (data->msgs[0].flags != 0) {
|
|
|
|
AP_HAL::panic("Unexpected flags");
|
|
|
|
}
|
|
|
|
const uint8_t reg_base_addr = data->msgs[0].buf[0];
|
|
|
|
uint8_t bytes_copied = 0;
|
|
|
|
while (bytes_copied < data->msgs[0].len-1) {
|
|
|
|
const uint8_t reg_addr = reg_base_addr + bytes_copied;
|
|
|
|
if (!writable_registers.get(reg_addr)) {
|
|
|
|
AP_HAL::panic("Register 0x%02x is not writable!", reg_addr);
|
|
|
|
}
|
|
|
|
const uint8_t register_value = data->msgs[0].buf[1+bytes_copied];
|
|
|
|
byte[reg_addr] = register_value;
|
|
|
|
bytes_copied++;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
};
|
2020-12-03 23:14:59 -04:00
|
|
|
|
|
|
|
|
2021-01-10 20:10:01 -04:00
|
|
|
void SITL::I2CRegisters_8Bit::assert_register_value(uint8_t reg, uint8_t value)
|
|
|
|
{
|
|
|
|
if (byte[reg] != value) {
|
|
|
|
AP_HAL::panic("Register 0x%02x (%s) was expected to have value (%02x) but has value (%02x)", reg, regname[reg], byte[reg], value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 23:14:59 -04:00
|
|
|
int SITL::I2CCommandResponseDevice::rdwr(I2C::i2c_rdwr_ioctl_data *&data)
|
|
|
|
{
|
|
|
|
const uint32_t now = AP_HAL::millis();
|
|
|
|
|
|
|
|
struct I2C::i2c_msg &msg = data->msgs[0];
|
|
|
|
if (msg.flags == I2C_M_RD) {
|
|
|
|
// driver is attempting to receive reading...
|
|
|
|
if (now - cmd_take_reading_received_ms < command_processing_time_ms()) {
|
|
|
|
// not sure we ought to be returning -1 here - what does
|
|
|
|
// the real device do? return stale data? garbage data?
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (msg.len != 2) {
|
|
|
|
AP_HAL::panic("Unxpected message length (%u)", msg.len);
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint16_t value = reading();
|
|
|
|
|
|
|
|
msg.buf[0] = value >> 8;
|
|
|
|
msg.buf[1] = value & 0xff;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t cmd = msg.buf[0];
|
|
|
|
if (cmd != command_take_reading()) {
|
|
|
|
AP_HAL::panic("Unknown command (%u)", cmd);
|
|
|
|
}
|
|
|
|
cmd_take_reading_received_ms = now;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|