[dif/adc_ctrl] Implement value-get DIFs

This implements the value-get DIFs and corresponding unit tests for the
ADC Controller.

Signed-off-by: Timothy Trippel <ttrippel@google.com>
diff --git a/sw/device/lib/dif/dif_adc_ctrl.c b/sw/device/lib/dif/dif_adc_ctrl.c
index 85a724f..6764d35 100644
--- a/sw/device/lib/dif/dif_adc_ctrl.c
+++ b/sw/device/lib/dif/dif_adc_ctrl.c
@@ -334,3 +334,61 @@
 
   return kDifOk;
 }
+
+dif_result_t dif_adc_ctrl_get_triggered_value(const dif_adc_ctrl_t *adc_ctrl,
+                                              dif_adc_ctrl_channel_t channel,
+                                              uint16_t *value) {
+  if (adc_ctrl == NULL || value == NULL) {
+    return kDifBadArg;
+  }
+
+  uint32_t value_reg;
+
+#define DIF_ADC_CTRL_CHANNEL_TRIG_VALUE_CASE_(channel_)                           \
+  case kDifAdcCtrlChannel##channel_:                                              \
+    value_reg = mmio_region_read32(                                               \
+        adc_ctrl->base_addr, ADC_CTRL_ADC_CHN_VAL_##channel_##_REG_OFFSET);       \
+    *value = bitfield_field32_read(                                               \
+        value_reg,                                                                \
+        ADC_CTRL_ADC_CHN_VAL_##channel_##_ADC_CHN_VALUE_INTR_##channel_##_FIELD); \
+    break;
+
+  switch (channel) {
+    DIF_ADC_CTRL_CHANNEL_LIST(DIF_ADC_CTRL_CHANNEL_TRIG_VALUE_CASE_)
+    default:
+      return kDifBadArg;
+  }
+
+#undef DIF_ADC_CTRL_CHANNEL_TRIG_VALUE_CASE_
+
+  return kDifOk;
+}
+
+dif_result_t dif_adc_ctrl_get_latest_value(const dif_adc_ctrl_t *adc_ctrl,
+                                           dif_adc_ctrl_channel_t channel,
+                                           uint16_t *value) {
+  if (adc_ctrl == NULL || value == NULL) {
+    return kDifBadArg;
+  }
+
+  uint32_t value_reg;
+
+#define DIF_ADC_CTRL_CHANNEL_LATEST_VALUE_CASE_(channel_)                    \
+  case kDifAdcCtrlChannel##channel_:                                         \
+    value_reg = mmio_region_read32(                                          \
+        adc_ctrl->base_addr, ADC_CTRL_ADC_CHN_VAL_##channel_##_REG_OFFSET);  \
+    *value = bitfield_field32_read(                                          \
+        value_reg,                                                           \
+        ADC_CTRL_ADC_CHN_VAL_##channel_##_ADC_CHN_VALUE_##channel_##_FIELD); \
+    break;
+
+  switch (channel) {
+    DIF_ADC_CTRL_CHANNEL_LIST(DIF_ADC_CTRL_CHANNEL_LATEST_VALUE_CASE_)
+    default:
+      return kDifBadArg;
+  }
+
+#undef DIF_ADC_CTRL_CHANNEL_LATEST_VALUE_CASE_
+
+  return kDifOk;
+}
diff --git a/sw/device/lib/dif/dif_adc_ctrl_unittest.cc b/sw/device/lib/dif/dif_adc_ctrl_unittest.cc
index f0671d0..162933b 100644
--- a/sw/device/lib/dif/dif_adc_ctrl_unittest.cc
+++ b/sw/device/lib/dif/dif_adc_ctrl_unittest.cc
@@ -326,5 +326,59 @@
   EXPECT_EQ(is_enabled, kDifToggleDisabled);
 }
 
+class GetTriggeredValueTest : public AdcCtrlTest {};
+
+TEST_F(GetTriggeredValueTest, NullArgs) {
+  uint16_t value;
+  EXPECT_DIF_BADARG(
+      dif_adc_ctrl_get_triggered_value(nullptr, kDifAdcCtrlChannel0, &value));
+  EXPECT_DIF_BADARG(dif_adc_ctrl_get_triggered_value(
+      &adc_ctrl_, kDifAdcCtrlChannel0, nullptr));
+}
+
+TEST_F(GetTriggeredValueTest, BadChannel) {
+  uint16_t value;
+  EXPECT_DIF_BADARG(dif_adc_ctrl_get_triggered_value(
+      &adc_ctrl_,
+      static_cast<dif_adc_ctrl_channel_t>(ADC_CTRL_PARAM_NUM_ADC_CHANNEL),
+      &value));
+}
+
+TEST_F(GetTriggeredValueTest, Success) {
+  uint16_t value;
+  EXPECT_READ32(ADC_CTRL_ADC_CHN_VAL_0_REG_OFFSET,
+                {{ADC_CTRL_ADC_CHN_VAL_0_ADC_CHN_VALUE_INTR_0_OFFSET, 1023}});
+  EXPECT_DIF_OK(dif_adc_ctrl_get_triggered_value(&adc_ctrl_,
+                                                 kDifAdcCtrlChannel0, &value));
+  EXPECT_EQ(value, 1023);
+}
+
+class GetLatestValueTest : public AdcCtrlTest {};
+
+TEST_F(GetLatestValueTest, NullArgs) {
+  uint16_t value;
+  EXPECT_DIF_BADARG(
+      dif_adc_ctrl_get_latest_value(nullptr, kDifAdcCtrlChannel0, &value));
+  EXPECT_DIF_BADARG(
+      dif_adc_ctrl_get_latest_value(&adc_ctrl_, kDifAdcCtrlChannel0, nullptr));
+}
+
+TEST_F(GetLatestValueTest, BadChannel) {
+  uint16_t value;
+  EXPECT_DIF_BADARG(dif_adc_ctrl_get_latest_value(
+      &adc_ctrl_,
+      static_cast<dif_adc_ctrl_channel_t>(ADC_CTRL_PARAM_NUM_ADC_CHANNEL),
+      &value));
+}
+
+TEST_F(GetLatestValueTest, Success) {
+  uint16_t value;
+  EXPECT_READ32(ADC_CTRL_ADC_CHN_VAL_0_REG_OFFSET,
+                {{ADC_CTRL_ADC_CHN_VAL_0_ADC_CHN_VALUE_0_OFFSET, 1023}});
+  EXPECT_DIF_OK(
+      dif_adc_ctrl_get_latest_value(&adc_ctrl_, kDifAdcCtrlChannel0, &value));
+  EXPECT_EQ(value, 1023);
+}
+
 }  // namespace
 }  // namespace dif_adc_ctrl_unittest