diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h
index ccd8a900d6f0aa58fa157536ad6c3eb4c62b6fa9..dbbe44da767255e05ac5942626b4035cab7390ba 100644
--- a/epicardium/modules/modules.h
+++ b/epicardium/modules/modules.h
@@ -27,11 +27,29 @@ void vSerialTask(void *pvParameters);
 void serial_enqueue_char(char chr);
 
 /* ---------- PMIC --------------------------------------------------------- */
-/* In 1/10s */
-#define PMIC_PRESS_SLEEP           20
-#define PMIC_PRESS_POWEROFF        40
 void vPmicTask(void *pvParameters);
 
+enum pmic_amux_signal {
+	PMIC_AMUX_CHGIN_U     = 0x1,
+	PMIC_AMUX_CHGIN_I     = 0x2,
+	PMIC_AMUX_BATT_U      = 0x3,
+	PMIC_AMUX_BATT_CHG_I  = 0x4,
+	PMIC_AMUX_BATT_DIS_I  = 0x5,
+	PMIC_AMUX_BATT_NULL_I = 0x6,
+	PMIC_AMUX_THM_U       = 0x7,
+	PMIC_AMUX_TBIAS_U     = 0x8,
+	PMIC_AMUX_AGND_U      = 0x9,
+	PMIC_AMUX_SYS_U       = 0xA,
+	_PMIC_AMUX_MAX,
+};
+
+/*
+ * Read a value from the PMIC's AMUX.  The result is already converted into its
+ * proper unit.  See the MAX77650 datasheet for details.
+ */
+int pmic_read_amux(enum pmic_amux_signal sig, float *result);
+
+
 /* ---------- BLE ---------------------------------------------------------- */
 void vBleTask(void *pvParameters);
 bool ble_shall_start(void);
diff --git a/epicardium/modules/pmic.c b/epicardium/modules/pmic.c
index c02691dc25350723b04bd0059183bcf0522396ae..7b7526e1c2f19d8bea75a1bda837a5f9da9cf173 100644
--- a/epicardium/modules/pmic.c
+++ b/epicardium/modules/pmic.c
@@ -1,17 +1,20 @@
-#include <stdio.h>
+#include "epicardium.h"
+#include "modules/modules.h"
+#include "modules/log.h"
 
-#include "max32665.h"
-#include "gcr_regs.h"
+#include "card10.h"
 #include "pmic.h"
 #include "MAX77650-Arduino-Library.h"
-#include "card10.h"
+
+#include "max32665.h"
+#include "mxc_sys.h"
+#include "mxc_pins.h"
+#include "adc.h"
 
 #include "FreeRTOS.h"
 #include "task.h"
 
-#include "epicardium.h"
-#include "modules.h"
-#include "modules/log.h"
+#include <stdio.h>
 
 /* Task ID for the pmic handler */
 static TaskHandle_t pmic_task_id = NULL;
@@ -25,10 +28,62 @@ void pmic_interrupt_callback(void *_)
 	}
 }
 
+int pmic_read_amux(enum pmic_amux_signal sig, float *result)
+{
+	int ret = 0;
+
+	if (sig > _PMIC_AMUX_MAX) {
+		return -EINVAL;
+	}
+
+	ret = hwlock_acquire(HWLOCK_ADC, pdMS_TO_TICKS(100));
+	if (ret < 0) {
+		return ret;
+	}
+	ret = hwlock_acquire(HWLOCK_I2C, pdMS_TO_TICKS(100));
+	if (ret < 0) {
+		return ret;
+	}
+
+	/* Select the correct channel for this measurement.  */
+	MAX77650_setMUX_SEL(sig);
+
+	uint16_t adc_data;
+	ADC_StartConvert(ADC_CH_0, 0, 0);
+	ADC_GetData(&adc_data);
+
+	/* Turn MUX back to neutral so it does not waste power.  */
+	MAX77650_setMUX_SEL(sig);
+
+	/* Convert ADC measurement to SI Volts */
+	float adc_voltage = (float)adc_data / 1023.0f * 1.22f;
+
+	/*
+	 * Convert value according to PMIC formulas (Table 7)
+	 */
+	switch (sig) {
+	case PMIC_AMUX_BATT_U:
+		*result = adc_voltage / 0.272f;
+		break;
+	case PMIC_AMUX_SYS_U:
+		*result = adc_voltage / 0.26f;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	hwlock_release(HWLOCK_I2C);
+	hwlock_release(HWLOCK_ADC);
+	return ret;
+}
+
 void vPmicTask(void *pvParameters)
 {
 	pmic_task_id = xTaskGetCurrentTaskHandle();
 
+	ADC_Init(0x9, NULL);
+	GPIO_Config(&gpio_cfg_adc0);
+
 	TickType_t button_start_tick = 0;
 
 	while (1) {