AS7331.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. /**
  2. * @file AS7331.hpp
  3. * @brief UV Spectral Sensor - AS7331 Driver
  4. *
  5. * This driver provides a communication interface for the AS7331 UV spectral sensor.
  6. * It includes configurations for I2C addressing, device modes, gain, clock frequency,
  7. * and measurement settings.
  8. *
  9. * Inspired by: https://github.com/sparkfun/SparkFun_AS7331_Arduino_Library/blob/main/src/sfeAS7331.h
  10. * Datasheet: https://look.ams-osram.com/m/1856fd2c69c35605/original/AS7331-Spectral-UVA-B-C-Sensor.pdf
  11. */
  12. #pragma once
  13. #include <stddef.h>
  14. #include <stdint.h>
  15. #include <furi_hal_i2c_types.h>
  16. /**
  17. * @defgroup AS7331_I2C_Addressing I2C Addressing
  18. * @brief I2C address definitions for AS7331
  19. *
  20. * The 7-bit I2C address is defined as [1, 1, 1, 0, 1, A1, A0], where A1 and A0 are configurable address pins.
  21. * @{
  22. */
  23. /** Default I2C address when A1 = 0, A0 = 0 */
  24. const uint8_t DefaultI2CAddr = 0x74;
  25. /** Secondary I2C address when A1 = 0, A0 = 1 */
  26. const uint8_t SecondaryI2CAddr = 0x75;
  27. /** Tertiary I2C address when A1 = 1, A0 = 0 */
  28. const uint8_t TertiaryI2CAddr = 0x76;
  29. /** Quaternary I2C address when A1 = 1, A0 = 1 */
  30. const uint8_t QuaternaryI2CAddr = 0x77;
  31. /** Expected API Generation Register content (Device ID + Mutation number) */
  32. const uint8_t ExpectedAGENContent = 0x21;
  33. /** @} */ // End of AS7331_I2C_Addressing group
  34. /**
  35. * @defgroup AS7331_Enums Enumerations
  36. * @brief Enumerations for AS7331 settings
  37. * @{
  38. */
  39. /**
  40. * @brief Device Operating Modes
  41. */
  42. enum as7331_device_mode_t : uint8_t {
  43. DEVICE_MODE_CONFIG = 0x2, /**< Configuration mode */
  44. DEVICE_MODE_MEASURE = 0x3 /**< Measurement mode */
  45. };
  46. /**
  47. * @brief Sensor Gain Settings (CREG1:GAIN)
  48. *
  49. * Default: GAIN_2 (1010)
  50. *
  51. * Gain value is calculated as:
  52. * **gain = 2<sup>(11 - gain_code)</sup>**
  53. */
  54. enum as7331_gain_t : uint8_t {
  55. GAIN_2048 = 0x0000,
  56. GAIN_1024,
  57. GAIN_512,
  58. GAIN_256,
  59. GAIN_128,
  60. GAIN_64,
  61. GAIN_32,
  62. GAIN_16,
  63. GAIN_8,
  64. GAIN_4,
  65. GAIN_2,
  66. GAIN_1
  67. };
  68. /**
  69. * @brief Integration Time Settings (CREG1:TIME)
  70. *
  71. * Default: TIME_64MS (0110)
  72. *
  73. * The conversion time in the enumerators (in milliseconds) is valid for a clock frequency of 1.024 MHz.
  74. * For higher clock frequencies, the conversion time is divided by 2 each time the clock frequency is doubled.
  75. *
  76. * **Conversion Time [ms] = 2<sup>integration_time_code</sup>**
  77. */
  78. enum as7331_integration_time_t : uint8_t {
  79. TIME_1MS = 0x0,
  80. TIME_2MS,
  81. TIME_4MS,
  82. TIME_8MS,
  83. TIME_16MS,
  84. TIME_32MS,
  85. TIME_64MS,
  86. TIME_128MS,
  87. TIME_256MS,
  88. TIME_512MS,
  89. TIME_1024MS,
  90. TIME_2048MS,
  91. TIME_4096MS,
  92. TIME_8192MS,
  93. TIME_16384MS
  94. };
  95. /**
  96. * @brief Divider Settings (CREG2:DIV)
  97. *
  98. * Default: DIV_2 (000)
  99. *
  100. * Divider value is calculated as:
  101. * **divider = 2<sup>(1 + divider_code)</sup>**
  102. */
  103. enum as7331_divider_t : uint8_t {
  104. DIV_2 = 0x0,
  105. DIV_4,
  106. DIV_8,
  107. DIV_16,
  108. DIV_32,
  109. DIV_64,
  110. DIV_128,
  111. DIV_256
  112. };
  113. /**
  114. * @brief Internal Clock Frequency Settings fCLK (CREG3:CCLK)
  115. *
  116. * Default: CCLK_1_024_MHZ
  117. *
  118. * Clock frequency is calculated as:
  119. * **clock_frequency = 1.024 × 2<sup>clock_frequency_code</sup>** (in MHz)
  120. */
  121. enum as7331_clock_frequency_t : uint8_t {
  122. CCLK_1_024_MHZ = 0x00, /**< 1.024 MHz: 1 - 16384 ms (Conversion Time) */
  123. CCLK_2_048_MHZ,
  124. CCLK_4_096_MHZ,
  125. CCLK_8_192_MHZ /**< 8.192 MHz: 0.125 - 2048 ms (Conversion Time) */
  126. };
  127. /**
  128. * @brief Measurement Modes (CREG3:MMODE)
  129. *
  130. * Default: MEASUREMENT_MODE_COMMAND (01)
  131. */
  132. enum as7331_measurement_mode_t : uint8_t {
  133. MEASUREMENT_MODE_CONTINUOUS = 0x0, /**< Continuous Measurement Mode (CONT) */
  134. MEASUREMENT_MODE_COMMAND, /**< Command Measurement Mode (CMD) */
  135. MEASUREMENT_MODE_SYNC_START, /**< Synchronous Measurement Mode (SYNS) - externally synchronized start of measurement */
  136. MEASUREMENT_MODE_SYNC_START_END /**< Synchronous Measurement Start and End Mode (SYND) - start and end of measurement are externally synchronized */
  137. };
  138. /** @brief UV Type Selection */
  139. enum as7331_uv_type_t : uint8_t {
  140. UV_A,
  141. UV_B,
  142. UV_C
  143. };
  144. /** @} */ // End of AS7331_Enums group
  145. /**
  146. * @defgroup AS7331_Config_Registers Configuration Register Definitions
  147. * @brief Definitions for configuration registers
  148. *
  149. * Registers are 8 bits long and can only be accessed in the configuration mode.
  150. * @{
  151. */
  152. /** @brief OSR configuration register address */
  153. const uint8_t RegCfgOsr = 0x00;
  154. /**
  155. * @brief Operational State Register (OSR) Register Layout
  156. */
  157. typedef union {
  158. struct {
  159. as7331_device_mode_t
  160. operating_state : 3; /**< DOS (010) - Device Operating State (OSR[2:0]) */
  161. uint8_t software_reset : 1; /**< SW_RES (0) - Software Reset (OSR[3]) */
  162. uint8_t reserved : 2; /**< Reserved, do not write (OSR[5:4]) */
  163. uint8_t power_down : 1; /**< PD (1) - Power Down (OSR[6]) */
  164. uint8_t start_state : 1; /**< SS (0) - Start State (OSR[7]) */
  165. };
  166. uint8_t byte;
  167. } as7331_osr_reg_t;
  168. /** @brief AGEN register address */
  169. const uint8_t RegCfgAgen = 0x02;
  170. /**
  171. * @brief AGEN Register Layout
  172. */
  173. typedef union {
  174. struct {
  175. uint8_t
  176. mutation : 4; /**< MUT (0001) - Mutation number of control register bank. Incremented when control registers change (AGEN[3:0]) */
  177. uint8_t device_id : 4; /**< DEVID (0010) - Device ID number (AGEN[7:4]) */
  178. };
  179. uint8_t byte;
  180. } as7331_agen_reg_t;
  181. /** @brief CREG1 -- Configuration Register 1 address */
  182. const uint8_t RegCfgCreg1 = 0x06;
  183. /**
  184. * @brief CREG1 Register Layout
  185. */
  186. typedef union {
  187. struct {
  188. as7331_integration_time_t
  189. integration_time : 4; /**< TIME (0110) - Integration time (CREG1[3:0]) */
  190. as7331_gain_t gain : 4; /**< GAIN (1010) - Sensor gain (CREG1[7:4]) */
  191. };
  192. uint8_t byte;
  193. } as7331_creg1_reg_t;
  194. /** @brief CREG2 -- Configuration Register 2 address */
  195. const uint8_t RegCfgCreg2 = 0x07;
  196. /**
  197. * @brief CREG2 Register Layout
  198. */
  199. typedef union {
  200. struct {
  201. as7331_divider_t divider : 3; /**< DIV (000) - Divider value (CREG2[2:0]) */
  202. uint8_t enable_divider : 1; /**< EN_DIV (0) - Divider enable (CREG2[3]) */
  203. uint8_t reserved : 2; /**< Reserved, do not write (CREG2[5:4]) */
  204. uint8_t
  205. enable_temp : 1; /**< EN_TM (1) - Temperature measurement enable in SYND mode (CREG2[6]) */
  206. uint8_t reserved1 : 1; /**< Reserved, do not write (CREG2[7]) */
  207. };
  208. uint8_t byte;
  209. } as7331_creg2_reg_t;
  210. /** @brief CREG3 -- Configuration Register 3 address */
  211. const uint8_t RegCfgCreg3 = 0x08;
  212. /**
  213. * @brief CREG3 Register Layout
  214. */
  215. typedef union {
  216. struct {
  217. as7331_clock_frequency_t
  218. clock_frequency : 2; /**< CCLK (00) - Internal clock frequency (CREG3[1:0]) */
  219. uint8_t reserved : 1; /**< Reserved, do not write (CREG3[2]) */
  220. uint8_t ready_mode : 1; /**< RDYOD (0) - Ready pin mode (CREG3[3]) */
  221. uint8_t standby : 1; /**< SB (0) - Standby mode (CREG3[4]) */
  222. uint8_t reserved1 : 1; /**< Reserved, do not write (CREG3[5]) */
  223. as7331_measurement_mode_t
  224. measurement_mode : 2; /**< MMODE (01) - Measurement mode selection (CREG3[7:6]) */
  225. };
  226. uint8_t byte;
  227. } as7331_creg3_reg_t;
  228. /** @brief BREAK register address */
  229. const uint8_t RegCfgBreak =
  230. 0x09; /**< BREAK (0x19) - Break time TBREAK between two measurements (except CMD mode) */
  231. /** @brief EDGES register address */
  232. const uint8_t RegCfgEdges = 0x0A; /**< EDGES (0x1) - Number of SYN falling edges */
  233. /** @brief OPTREG - Option Register address */
  234. const uint8_t RegCfgOptReg = 0x0B;
  235. /**
  236. * @brief OPTREG Register Layout
  237. */
  238. typedef union {
  239. struct {
  240. uint8_t init_idx : 1; /**< INIT_IDX (1) - I2C repeat start mode flag (OPTREG[0]) */
  241. uint8_t reserved : 7; /**< Reserved, do not write (OPTREG[7:1]) */
  242. };
  243. uint8_t byte;
  244. } as7331_optreg_reg_t;
  245. /** @} */ // End of AS7331_Config_Registers group
  246. /**
  247. * @defgroup AS7331_Measurement_Registers Measurement Register Definitions
  248. * @brief Definitions for measurement registers
  249. *
  250. * Registers are 16 bits long and read-only, except for the lower byte of the OSR/STATUS register.
  251. * @{
  252. */
  253. /** @brief OSR/Status register address */
  254. const uint8_t RegMeasOsrStatus = 0x00;
  255. /**
  256. * @brief OSR/STATUS Register Layout
  257. */
  258. typedef union {
  259. struct {
  260. as7331_osr_reg_t osr; /**< OSR settings (lower byte) (OSRSTAT[7:0]) */
  261. uint8_t power_state : 1; /**< POWERSTATE - Power Down state (OSRSTAT[8]) */
  262. uint8_t standby_state : 1; /**< STANDBYSTATE - Standby mode state (OSRSTAT[9]) */
  263. uint8_t not_ready : 1; /**< NOTREADY - Inverted ready pin state (OSRSTAT[10]) */
  264. uint8_t new_data : 1; /**< NDATA - New data available (OSRSTAT[11]) */
  265. uint8_t lost_data : 1; /**< LDATA - Data overwritten before retrieval (OSRSTAT[12]) */
  266. uint8_t adc_overflow : 1; /**< ADCOF - Overflow of ADC channel (OSRSTAT[13]) */
  267. uint8_t result_overflow : 1; /**< MRESOF - Overflow of MRES1...MRES3 (OSRSTAT[14]) */
  268. uint8_t
  269. out_conv_overflow : 1; /**< OUTCONVOF - Overflow of internal 24-bit OUTCONV (OSRSTAT[15]) */
  270. };
  271. uint16_t word;
  272. } as7331_osr_status_reg_t;
  273. /** @brief TEMP register address (12-bit temperature, MS 4 bits are 0) */
  274. const uint8_t RegMeasTemp = 0x01;
  275. /** @brief MRES1 register address - Measurement Result A */
  276. const uint8_t RegMeasResultA = 0x02;
  277. /** @brief MRES2 register address - Measurement Result B */
  278. const uint8_t RegMeasResultB = 0x03;
  279. /** @brief MRES3 register address - Measurement Result C */
  280. const uint8_t RegMeasResultC = 0x04;
  281. /** @brief OUTCONVL register address - First 16 bits of 24-bit OUTCONV */
  282. const uint8_t RegMeasOutConvL = 0x05;
  283. /** @brief OUTCONVH register address - Upper 8 bits of OUTCONV, MSB is 0 */
  284. const uint8_t RegMeasOutConvH = 0x06;
  285. /** @} */ // End of AS7331_Measurement_Registers group
  286. /**
  287. * @brief AS7331 UV Spectral Sensor Driver
  288. *
  289. * This class provides an interface for the AS7331 UV spectral sensor,
  290. * allowing configuration and measurement.
  291. */
  292. class AS7331 {
  293. public:
  294. /** @brief Struct to hold raw measurement results */
  295. struct RawResults {
  296. uint16_t uv_a; /**< Raw measurement for UV-A channel */
  297. uint16_t uv_b; /**< Raw measurement for UV-B channel */
  298. uint16_t uv_c; /**< Raw measurement for UV-C channel */
  299. };
  300. /** @brief Struct to hold processed measurement results */
  301. struct Results {
  302. double uv_a; /**< Irradiance for UV-A in µW/cm² */
  303. double uv_b; /**< Irradiance for UV-B in µW/cm² */
  304. double uv_c; /**< Irradiance for UV-C in µW/cm² */
  305. };
  306. /**
  307. * @brief Constructs an AS7331 sensor object
  308. *
  309. * @param address I2C address of the sensor (default is DefaultI2CAddr)
  310. */
  311. AS7331(uint8_t address = DefaultI2CAddr);
  312. /**
  313. * @brief Initialize the sensor
  314. *
  315. * @param address I2C address in 7-bit format. If 0x0, scan the I2C bus to find the device.
  316. * @return true if initialization is successful, false otherwise
  317. */
  318. bool init(const uint8_t& address = 0);
  319. // Configuration methods
  320. /**
  321. * @brief Set sensor gain (CREG1:GAIN)
  322. *
  323. * @param gain Gain setting from as7331_gain_t
  324. * @return true if successful, false otherwise
  325. */
  326. bool setGain(const as7331_gain_t& gain);
  327. /**
  328. * @brief Set integration time (CREG1:TIME)
  329. *
  330. * @param time Integration time setting from as7331_integration_time_t
  331. * @return true if successful, false otherwise
  332. */
  333. bool setIntegrationTime(const as7331_integration_time_t& time);
  334. /**
  335. * @brief Set output divider (CREG2:DIV)
  336. *
  337. * @param divider Divider setting from as7331_divider_t
  338. * @param enable Enable or disable the divider
  339. * @return true if successful, false otherwise
  340. */
  341. bool setDivider(const as7331_divider_t& divider, const bool enable = true);
  342. /**
  343. * @brief Set clock frequency (CREG3:CCLK)
  344. *
  345. * @param freq Clock frequency setting from as7331_clock_frequency_t
  346. * @return true if successful, false otherwise
  347. */
  348. bool setClockFrequency(const as7331_clock_frequency_t& freq);
  349. /**
  350. * @brief Set measurement mode (CREG3:MMODE)
  351. *
  352. * @param mode Measurement mode setting from as7331_measurement_mode_t
  353. * @return true if successful, false otherwise
  354. */
  355. bool setMeasurementMode(const as7331_measurement_mode_t& mode);
  356. // Power management
  357. /**
  358. * @brief Enable or disable power-down state (OSR:PD)
  359. *
  360. * @param power_down true to enable power-down, false to disable
  361. * @return true if successful, false otherwise
  362. */
  363. bool setPowerDown(const bool& power_down);
  364. /**
  365. * @brief Enable or disable standby mode (CREG3:SB)
  366. *
  367. * @param standby true to enable standby, false to disable
  368. * @return true if successful, false otherwise
  369. */
  370. bool setStandby(const bool& standby);
  371. // Measurement methods
  372. /**
  373. * @brief Start the measurement (OSR:SS = 1)
  374. *
  375. * @return true if successful, false otherwise
  376. */
  377. bool startMeasurement();
  378. /**
  379. * @brief Stop the measurement (OSR:SS = 0)
  380. *
  381. * @return true if successful, false otherwise
  382. */
  383. bool stopMeasurement();
  384. /**
  385. * @brief Wait for the measurement to complete based on conversion time
  386. */
  387. void waitForMeasurement();
  388. /**
  389. * @brief Get raw measurement results
  390. *
  391. * Before reading results, wait an appropriate amount of time for the measurement to complete (TCONV).
  392. *
  393. * @param rawResults Struct to hold raw measurement results
  394. * @return true if successful, false otherwise
  395. */
  396. bool getRawResults(RawResults& rawResults);
  397. /**
  398. * @brief Get processed measurement results
  399. *
  400. * Before reading results, wait an appropriate amount of time for the measurement to complete (TCONV).
  401. *
  402. * @param results Struct to hold processed measurement results
  403. * @param rawResults Struct to hold raw measurement results
  404. * @return true if successful, false otherwise
  405. */
  406. bool getResults(Results& results, RawResults& rawResults);
  407. /**
  408. * @brief Get processed measurement results
  409. *
  410. * Before reading results, wait an appropriate amount of time for the measurement to complete (TCONV).
  411. *
  412. * @param results Struct to hold processed measurement results
  413. * @return true if successful, false otherwise
  414. */
  415. bool getResults(Results& results);
  416. /**
  417. * @brief Get temperature measurement
  418. *
  419. * Before reading results, wait an appropriate amount of time for the measurement to complete (TCONV).
  420. *
  421. * @param temperature Temperature in degrees Celsius
  422. * @return true if successful, false otherwise
  423. */
  424. bool getTemperature(double& temperature);
  425. // Utility methods
  426. /**
  427. * @brief Check if the device is ready
  428. *
  429. * @param i2c_address_7bit I2C address in 7-bit format (default uses internal address)
  430. * @return true if device is ready, false otherwise
  431. */
  432. bool deviceReady(const uint8_t& i2c_address_7bit = 0);
  433. /**
  434. * @brief Perform a software reset
  435. *
  436. * This immediately stops any running measurements and resets the device to its configuration state,
  437. * with all registers reverting to their initial values.
  438. *
  439. * @return true if the reset was successful, false otherwise
  440. */
  441. bool reset();
  442. // Getter methods
  443. /**
  444. * @brief Get device ID (including mutation number)
  445. *
  446. * @param deviceID Struct to hold device ID
  447. * @return true if successful, false otherwise
  448. */
  449. bool getDeviceID(as7331_agen_reg_t& deviceID);
  450. /**
  451. * @brief Get status register in measurement mode
  452. *
  453. * @param status Struct to hold status register data
  454. * @return true if successful, false otherwise
  455. */
  456. bool getStatus(as7331_osr_status_reg_t& status);
  457. // Local config getter methods
  458. /**
  459. * @brief Get current gain setting
  460. *
  461. * @return Current gain setting as as7331_gain_t
  462. */
  463. as7331_gain_t getGain() const;
  464. /**
  465. * @brief Get actual gain value
  466. *
  467. * @return Gain value as integer
  468. */
  469. int16_t getGainValue() const;
  470. /**
  471. * @brief Get current integration time setting
  472. *
  473. * @return Current integration time as as7331_integration_time_t
  474. */
  475. as7331_integration_time_t getIntegrationTime() const;
  476. /**
  477. * @brief Get current conversion time in seconds
  478. *
  479. * @return Conversion time in seconds
  480. */
  481. double getConversionTime() const;
  482. /**
  483. * @brief Get current divider setting
  484. *
  485. * @return Current divider setting as as7331_divider_t
  486. */
  487. as7331_divider_t getDivider() const;
  488. /**
  489. * @brief Check if divider is enabled
  490. *
  491. * @return true if divider is enabled, false otherwise
  492. */
  493. bool isDividerEnabled() const;
  494. /**
  495. * @brief Get actual divider value
  496. *
  497. * @return Divider value as integer
  498. */
  499. uint8_t getDividerValue() const;
  500. /**
  501. * @brief Get current clock frequency setting
  502. *
  503. * @return Current clock frequency as as7331_clock_frequency_t
  504. */
  505. as7331_clock_frequency_t getClockFrequency() const;
  506. /**
  507. * @brief Get actual clock frequency value
  508. *
  509. * @return Clock frequency in MHz
  510. */
  511. double getClockFrequencyValue() const;
  512. /**
  513. * @brief Get current measurement mode
  514. *
  515. * @return Current measurement mode as as7331_measurement_mode_t
  516. */
  517. as7331_measurement_mode_t getMeasurementMode() const;
  518. /**
  519. * @brief Check if power-down is enabled
  520. *
  521. * @return true if power-down is enabled, false otherwise
  522. */
  523. bool isPowerDown() const;
  524. /**
  525. * @brief Check if standby mode is enabled
  526. *
  527. * @return true if standby is enabled, false otherwise
  528. */
  529. bool isStandby() const;
  530. private:
  531. // Internal helper methods
  532. /**
  533. * @brief Set the device mode
  534. *
  535. * @param mode Device mode to set
  536. * @return true if successful, false otherwise
  537. */
  538. bool setDeviceMode(const as7331_device_mode_t& mode);
  539. /**
  540. * @brief Read OSR register and update local config
  541. *
  542. * @param osr Struct to hold OSR register data
  543. * @return true if successful, false otherwise
  544. */
  545. bool readOSRRegister(as7331_osr_reg_t& osr);
  546. /**
  547. * @brief Write OSR register and update local config
  548. *
  549. * @param osr OSR register data to write
  550. * @return true if successful, false otherwise
  551. */
  552. bool writeOSRRegister(const as7331_osr_reg_t& osr);
  553. /**
  554. * @defgroup AS7331_I2C_Methods AS7331 Custom I2C Methods
  555. * @brief Custom I2C read and write functions for the AS7331 sensor.
  556. *
  557. * These functions utilize a "repeated start" condition instead of terminating each transaction with a STOP condition, as required by the AS7331.
  558. * This is achieved using `FuriHalI2cEndAwaitRestart` and `FuriHalI2cBeginRestart`, despite their documentation referring to "Clock Stretching," which the AS7331 does not support.
  559. *
  560. * @note The caller is responsible for calling `furi_hal_i2c_acquire` and `furi_hal_i2c_release`.
  561. * @{
  562. */
  563. /**
  564. * @brief Read multiple bytes from consecutive registers
  565. *
  566. * @param start_register_addr Starting register address
  567. * @param buffer Buffer to store read data
  568. * @param length Number of bytes to read
  569. * @return true if successful, false otherwise
  570. * @ingroup AS7331_I2C_Methods
  571. */
  572. bool readRegisters(uint8_t start_register_addr, uint8_t* buffer, size_t length);
  573. /**
  574. * @brief Read an 8-bit register
  575. *
  576. * @param register_addr Register address to read
  577. * @param data Variable to store read data
  578. * @return true if successful, false otherwise
  579. * @ingroup AS7331_I2C_Methods
  580. */
  581. bool readRegister(uint8_t register_addr, uint8_t& data);
  582. /**
  583. * @brief Read a 16-bit register
  584. *
  585. * @param register_addr Register address to read
  586. * @param data Variable to store read data
  587. * @return true if successful, false otherwise
  588. * @ingroup AS7331_I2C_Methods
  589. */
  590. bool readRegister16(uint8_t register_addr, uint16_t& data);
  591. /**
  592. * @brief Write an 8-bit register
  593. *
  594. * @param register_addr Register address to write
  595. * @param data Data to write
  596. * @return true if successful, false otherwise
  597. * @ingroup AS7331_I2C_Methods
  598. */
  599. bool writeRegister(uint8_t register_addr, const uint8_t& data);
  600. /** @} */ // End of AS7331_I2C_Methods group
  601. /**
  602. * @brief Scan I2C bus for AS7331 device
  603. *
  604. * @return Found I2C address in 7-bit format, 0 if not found
  605. */
  606. uint8_t scan_i2c_bus();
  607. /**
  608. * @brief Update local configuration variables from device registers
  609. *
  610. * @return true if successful, false otherwise
  611. */
  612. bool updateLocalConfig();
  613. /**
  614. * @brief Calculate Full-Scale Range (FSREe) for a given UV type
  615. *
  616. * @param uvType UV type (UV_A, UV_B, UV_C)
  617. * @param adjustForIntegrationTime Optional. A boolean flag indicating whether to adjust FSREe for the integration TIME setting. Default is `true`.
  618. * @return FSREe value in µW/cm², `-1.0` if an error occurs
  619. */
  620. double calculateFSREe(as7331_uv_type_t uvType, bool adjustForIntegrationTime = true);
  621. // Private member variables
  622. uint8_t _i2c_addr_8bit;
  623. as7331_device_mode_t _deviceMode;
  624. bool _power_down;
  625. as7331_gain_t _gain; /**< Gain code (0 to 11) */
  626. as7331_integration_time_t _integration_time; /**< Integration time code (0 to 15) */
  627. bool _enable_divider; /**< Divider enabled (CREG2:EN_DIV) */
  628. as7331_divider_t _divider; /**< Divider value (CREG2:DIV) */
  629. as7331_clock_frequency_t _clock_frequency; /**< Clock frequency code (0 to 3) */
  630. bool _standby;
  631. as7331_measurement_mode_t _measurement_mode;
  632. };