LCOV - code coverage report
Current view: top level - SITL - SIM_I2CDevice.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 94 177 53.1 %
Date: 2026-09-09 11:02:08 Functions: 10 16 62.5 %

          Line data    Source code
       1             : #include "SIM_I2CDevice.h"
       2             : #include <AP_HAL/utility/sparse-endian.h>
       3             : 
       4             : #ifndef HAL_DEBUG_I2DEVICE
       5             : #define HAL_DEBUG_I2DEVICE 0
       6             : #endif
       7             : 
       8             : #if HAL_DEBUG_I2DEVICE
       9             : #include <GCS_MAVLink/GCS.h>
      10             : #define DEBUG(fmt, args ...)  do { if (get_debug()) { GCS_SEND_TEXT(MAV_SEVERITY_INFO, fmt, ## args); } } while (0)
      11             : #else
      12             : #define DEBUG(fmt, args ...)
      13             : #endif
      14             : 
      15      288765 : void SITL::I2CRegisters::add_register(const char *name, uint8_t reg, RegMode mode)
      16             : {
      17             :     DEBUG("Adding register %u (0x%02x) (%s)", reg, reg, name);
      18      288765 :     regname[reg] = name;
      19      288765 :     if (mode == RegMode::RDONLY || mode == RegMode::RDWR) {
      20      215475 :         readable_registers.set((uint8_t)reg);
      21             :     }
      22      288765 :     if (mode == RegMode::WRONLY || mode == RegMode::RDWR) {
      23      123546 :         writable_registers.set((uint8_t)reg);
      24             :     }
      25      288765 : }
      26             : 
      27  3758438810 : void SITL::I2CRegisters_16Bit::set_register(uint8_t reg, uint16_t value)
      28             : {
      29  3758438810 :     if (regname[reg] == nullptr) {
      30           0 :         AP_HAL::panic("Setting un-named register %u", reg);
      31             :     }
      32             :     DEBUG("Setting %u (0x%02x) (%s) to 0x%02x", (unsigned)reg, (unsigned)reg, regname[reg], (unsigned)value);
      33             : 
      34  3758438810 :     word[reg] = htobe16(value);
      35  3758438810 : }
      36             : 
      37     4574081 : void SITL::I2CRegisters_16Bit::set_register(uint8_t reg, int16_t value)
      38             : {
      39     4574081 :     if (regname[reg] == nullptr) {
      40           0 :         AP_HAL::panic("Setting un-named register %u", reg);
      41             :     }
      42             :     DEBUG("Setting %s (%u) to 0x%02x", regname[reg], (unsigned)reg, (signed)value);
      43     4574081 :     word[reg] = htobe16(value);
      44     4574081 : }
      45             : 
      46        7686 : int SITL::I2CRegisters_16Bit::rdwr(I2C::i2c_rdwr_ioctl_data *&data)
      47             : {
      48        7686 :     if (data->nmsgs == 2) {
      49             :         // data read request
      50        7685 :         if (data->msgs[0].flags != 0) {
      51           0 :             AP_HAL::panic("Unexpected flags");
      52             :         }
      53        7685 :         if (data->msgs[1].flags != I2C_M_RD) {
      54           0 :             AP_HAL::panic("Unexpected flags");
      55             :         }
      56        7685 :         const uint8_t reg_base_addr = data->msgs[0].buf[0];
      57        7685 :         uint8_t bytes_copied = 0;
      58       14985 :         while (bytes_copied < data->msgs[1].len) {
      59        7697 :             const uint8_t reg_addr = reg_base_addr + bytes_copied/2;
      60        7697 :             if (!readable_registers.get(reg_addr)) {
      61             :                 // ::printf("Register 0x%02x is not readable!\n", reg_addr);
      62         397 :                 return -1;
      63             :             }
      64        7300 :             const uint16_t register_value = word[reg_addr];
      65        7300 :             data->msgs[1].buf[bytes_copied++] = register_value >> 8;
      66        7300 :             if (bytes_copied < data->msgs[1].len) {
      67        7300 :                 data->msgs[1].buf[bytes_copied++] = register_value & 0xFF;
      68             :             }
      69             :         }
      70        7288 :         data->msgs[1].len = bytes_copied;
      71        7288 :         return 0;
      72             :     }
      73             : 
      74           1 :     if (data->nmsgs == 1) {
      75             :         // data write request
      76           1 :         if (data->msgs[0].flags != 0) {
      77           0 :             AP_HAL::panic("Unexpected flags");
      78             :         }
      79             :         // FIXME: handle multi-register writes
      80           1 :         const uint8_t reg_addr = data->msgs[0].buf[0];
      81           1 :         if (!writable_registers.get(reg_addr)) {
      82           0 :             AP_HAL::panic("Register 0x%02x is not writable!", reg_addr);
      83             :         }
      84           1 :         const uint16_t register_value = data->msgs[0].buf[2] << 8 | data->msgs[0].buf[1];
      85           1 :         word[reg_addr] = register_value;
      86           1 :         return 0;
      87             :     }
      88             : 
      89           0 :     return -1;
      90             : };
      91             : 
      92             : 
      93             : 
      94   357608651 : void SITL::I2CRegisters_8Bit::set_register(uint8_t reg, uint8_t value)
      95             : {
      96   357608651 :     if (regname[reg] == nullptr) {
      97           0 :         AP_HAL::panic("Setting un-named register %u", reg);
      98             :     }
      99             :     DEBUG("Setting %u (0x%02x) (%s) to 0x%02x (%c)", (unsigned)reg, (unsigned)reg, regname[reg], (unsigned)value, value);
     100   357608651 :     byte[reg] = value;
     101   357608651 : }
     102             : 
     103           0 : void SITL::I2CRegisters_8Bit::set_register(uint8_t reg, int8_t value)
     104             : {
     105           0 :     if (regname[reg] == nullptr) {
     106           0 :         AP_HAL::panic("Setting un-named register %u", reg);
     107             :     }
     108             :     DEBUG("Setting %s (%u) to 0x%02x (%c)", regname[reg], (unsigned)reg, (signed)value, value);
     109           0 :     byte[reg] = value;
     110           0 : }
     111             : 
     112     2356563 : int SITL::I2CRegisters_8Bit::rdwr(I2C::i2c_rdwr_ioctl_data *&data)
     113             : {
     114     2356563 :     if (data->nmsgs == 2) {
     115             :         // data read request
     116       10471 :         if (data->msgs[0].flags != 0) {
     117           0 :             AP_HAL::panic("Unexpected flags");
     118             :         }
     119       10471 :         if (data->msgs[1].flags != I2C_M_RD) {
     120           0 :             AP_HAL::panic("Unexpected flags");
     121             :         }
     122       10471 :         const uint8_t reg_base_addr = data->msgs[0].buf[0];
     123       10471 :         uint8_t bytes_copied = 0;
     124       20942 :         while (bytes_copied < data->msgs[1].len) {
     125       10471 :             const uint8_t reg_addr = reg_base_addr + bytes_copied;
     126       10471 :             if (!readable_registers.get(reg_addr)) {
     127             :                 // ::printf("Register 0x%02x is not readable!\n", reg_addr);
     128           0 :                 return -1;
     129             :             }
     130       10471 :             const uint8_t register_value = byte[reg_addr];
     131       10471 :             data->msgs[1].buf[bytes_copied++] = register_value;
     132             :         }
     133       10471 :         data->msgs[1].len = bytes_copied;
     134       10471 :         return 0;
     135             :     }
     136             : 
     137     2346092 :     if (data->nmsgs == 1) {
     138             :         // data write request
     139     2346092 :         if (data->msgs[0].flags != 0) {
     140           0 :             AP_HAL::panic("Unexpected flags");
     141             :         }
     142     2346092 :         const uint8_t reg_base_addr = data->msgs[0].buf[0];
     143     2346092 :         uint8_t bytes_copied = 0;
     144     5424334 :         while (bytes_copied < data->msgs[0].len-1) {
     145     3078242 :             const uint8_t reg_addr = reg_base_addr + bytes_copied;
     146     3078242 :             if (!writable_registers.get(reg_addr)) {
     147           0 :                 AP_HAL::panic("Register 0x%02x is not writable!", reg_addr);
     148             :             }
     149     3078242 :             const uint8_t register_value = data->msgs[0].buf[1+bytes_copied];
     150     3078242 :             rdwr_store_register_value(reg_addr, register_value);
     151     3078242 :             bytes_copied++;
     152             :         }
     153     2346092 :         return 0;
     154             :     }
     155             : 
     156           0 :     return -1;
     157             : };
     158             : 
     159             : 
     160           0 : void SITL::I2CRegisters_8Bit::assert_register_value(uint8_t reg, uint8_t value)
     161             : {
     162           0 :     if (byte[reg] != value) {
     163           0 :         AP_HAL::panic("Register 0x%02x (%s) was expected to have value (%02x) but has value (%02x)", reg, regname[reg], byte[reg], value);
     164             :     }
     165           0 : }
     166             : 
     167        9012 : int SITL::I2CCommandResponseDevice::rdwr(I2C::i2c_rdwr_ioctl_data *&data)
     168             : {
     169        9012 :     const uint32_t now = AP_HAL::millis();
     170             : 
     171        9012 :     struct I2C::i2c_msg &msg = data->msgs[0];
     172        9012 :     if (msg.flags == I2C_M_RD) {
     173             :         // driver is attempting to receive reading...
     174        4502 :         if (now - cmd_take_reading_received_ms < command_processing_time_ms()) {
     175             :             // not sure we ought to be returning -1 here - what does
     176             :             // the real device do?  return stale data?  garbage data?
     177           0 :             return -1;
     178             :         }
     179        4502 :         if (msg.len != 2) {
     180           0 :             AP_HAL::panic("Unxpected message length (%u)", msg.len);
     181             :         }
     182             : 
     183        4502 :         const uint16_t value = reading();
     184             : 
     185        4502 :         msg.buf[0] = value >> 8;
     186        4502 :         msg.buf[1] = value & 0xff;
     187             : 
     188        4502 :         return 0;
     189             :     }
     190             : 
     191        4510 :     const uint8_t cmd = msg.buf[0];
     192        4510 :     if (cmd != command_take_reading()) {
     193           0 :         AP_HAL::panic("Unknown command (%u)", cmd);
     194             :     }
     195        4510 :     cmd_take_reading_received_ms = now;
     196             : 
     197        4510 :     return 0;
     198             : }
     199             : 
     200             : 
     201        8376 : void SITL::I2CRegisters_ConfigurableLength::add_register(const char *name, uint8_t reg, uint8_t len, RegMode mode)
     202             : {
     203        8376 :     SITL::I2CRegisters::add_register(name, reg, mode);
     204        8376 :     if (len > 4) {
     205           0 :         AP_HAL::panic("Only up to 4 bytes");
     206             :     }
     207        8376 :     reg_data_len[reg] = len;
     208        8376 : }
     209             : 
     210           0 : void SITL::I2CRegisters_ConfigurableLength::set_register(uint8_t reg, uint16_t value)
     211             : {
     212           0 :     if (regname[reg] == nullptr) {
     213           0 :         AP_HAL::panic("Setting un-named register %u", reg);
     214             :     }
     215             :     DEBUG("Setting %u (0x%02x) (%s) to 0x%02x", (unsigned)reg, (unsigned)reg, regname[reg], (unsigned)value);
     216             : 
     217           0 :     if (reg_data_len[reg] != 2) {
     218           0 :         AP_HAL::panic("Invalid set_register len");
     219             :     }
     220           0 :     reg_data[reg] = htobe16(value);
     221           0 : }
     222             : 
     223           0 : void SITL::I2CRegisters_ConfigurableLength::set_register(uint8_t reg, int16_t value)
     224             : {
     225           0 :     if (regname[reg] == nullptr) {
     226           0 :         AP_HAL::panic("Setting un-named register %u", reg);
     227             :     }
     228             :     DEBUG("Setting %s (%u) to 0x%02x", regname[reg], (unsigned)reg, (signed)value);
     229             : 
     230           0 :     if (reg_data_len[reg] != 2) {
     231           0 :         AP_HAL::panic("Invalid set_register len");
     232             :     }
     233           0 :     reg_data[reg] = htobe16(value);
     234           0 : }
     235             : 
     236        6282 : void SITL::I2CRegisters_ConfigurableLength::set_register(uint8_t reg, uint8_t value)
     237             : {
     238        6282 :     if (regname[reg] == nullptr) {
     239           0 :         AP_HAL::panic("Setting un-named register %u", reg);
     240             :     }
     241             :     DEBUG("Setting %u (0x%02x) (%s) to 0x%02x (%c)", (unsigned)reg, (unsigned)reg, regname[reg], (unsigned)value, value);
     242        6282 :     if (reg_data_len[reg] != 1) {
     243           0 :         AP_HAL::panic("Invalid set_register len");
     244             :     }
     245        6282 :     reg_data[reg] = value << 24;
     246        6282 : }
     247             : 
     248           0 : void SITL::I2CRegisters_ConfigurableLength::set_register(uint8_t reg, int8_t value)
     249             : {
     250           0 :     if (regname[reg] == nullptr) {
     251           0 :         AP_HAL::panic("Setting un-named register %u", reg);
     252             :     }
     253             :     DEBUG("Setting %s (%u) to 0x%02x (%c)", regname[reg], (unsigned)reg, (signed)value, value);
     254           0 :     if (reg_data_len[reg] != 1) {
     255           0 :         AP_HAL::panic("Invalid set_register len");
     256             :     }
     257           0 :     reg_data[reg] = value << 24;
     258           0 : }
     259             : 
     260           0 : int SITL::I2CRegisters_ConfigurableLength::rdwr(I2C::i2c_rdwr_ioctl_data *&data)
     261             : {
     262           0 :     if (data->nmsgs == 2) {
     263             :         // data read request
     264           0 :         if (data->msgs[0].flags != 0) {
     265           0 :             AP_HAL::panic("Unexpected flags");
     266             :         }
     267           0 :         if (data->msgs[1].flags != I2C_M_RD) {
     268           0 :             AP_HAL::panic("Unexpected flags");
     269             :         }
     270           0 :         const uint8_t reg_addr = data->msgs[0].buf[0];
     271           0 :         if (data->msgs[1].len != reg_data_len[reg_addr]) {
     272           0 :             AP_HAL::panic("Invalid rdwr len");
     273             :         }
     274           0 :         if (!readable_registers.get(reg_addr)) {
     275             :             // ::printf("Register 0x%02x is not readable!\n", reg_addr);
     276           0 :             return -1;
     277             :         }
     278           0 :         const uint32_t register_value = reg_data[reg_addr];
     279           0 :         if (data->msgs[1].len == 1) {
     280           0 :             data->msgs[1].buf[0] = register_value >> 24;
     281           0 :         } else if (data->msgs[1].len == 2) {
     282           0 :             const uint16_t v = htobe16(register_value & 0xffff);
     283           0 :             memcpy(&(data->msgs[1].buf[0]), &v, 2);
     284             :         } else {
     285           0 :             AP_HAL::panic("Bad length"); // FIXME
     286             :         }
     287           0 :         data->msgs[1].len = reg_data_len[reg_addr];
     288           0 :         return 0;
     289             :     }
     290             : 
     291           0 :     if (data->nmsgs == 1) {
     292             :         // data write request
     293           0 :         if (data->msgs[0].flags != 0) {
     294           0 :             AP_HAL::panic("Unexpected flags");
     295             :         }
     296             :         // FIXME: handle multi-register writes
     297           0 :         const uint8_t reg_addr = data->msgs[0].buf[0];
     298           0 :         if (!writable_registers.get(reg_addr)) {
     299           0 :             AP_HAL::panic("Register 0x%02x is not writable!", reg_addr);
     300             :         }
     301           0 :         const uint8_t data_msg_len = data->msgs[0].len - 1;
     302           0 :         if (data_msg_len != reg_data_len[reg_addr]) {
     303           0 :             AP_HAL::panic("Invalid rdwr len");
     304             :         }
     305           0 :         memcpy((uint8_t*)&reg_data[reg_addr], &data->msgs[0].buf[1], data_msg_len);
     306           0 :         return 0;
     307             :     }
     308             : 
     309           0 :     return -1;
     310             : };
     311             : 
     312     1488167 : void SITL::I2CRegisters_ConfigurableLength::get_reg_value(uint8_t reg, uint8_t &value) const
     313             : {
     314     1488167 :     if (reg_data_len[reg] != 1) {
     315           0 :             AP_HAL::panic("Invalid reg_reg_value len");
     316             :     }
     317     1488167 :     value = reg_data[reg];
     318     1488167 : }

Generated by: LCOV version 1.14