diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h
index 3555ab52e7c8ed66707459f2b0b4c90bf123dadd..57ebe42515f2450f8b9938220c795f012e6c27d5 100644
--- a/epicardium/modules/modules.h
+++ b/epicardium/modules/modules.h
@@ -32,11 +32,29 @@ void vLedTask(void *pvParameters);
 int personal_state_enabled();
 
 /* ---------- 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..57b305c89ad5c9656684a3e79ea482c05c42619e 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,89 @@ 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);
+
+	/*
+	 * According to the datasheet, the voltage will stabilize within 0.3us.
+	 * Just to be sure, we'll wait a little longer.  In the meantime,
+	 * release the I2C mutex.
+	 */
+	hwlock_release(HWLOCK_I2C);
+	vTaskDelay(pdMS_TO_TICKS(5));
+	ret = hwlock_acquire(HWLOCK_I2C, pdMS_TO_TICKS(100));
+	if (ret < 0) {
+		return ret;
+	}
+
+	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_CHGIN_U:
+		*result = adc_voltage / 0.167f;
+		break;
+	case PMIC_AMUX_CHGIN_I:
+		*result = adc_voltage / 2.632f;
+		break;
+	case PMIC_AMUX_BATT_U:
+		*result = adc_voltage / 0.272f;
+		break;
+	case PMIC_AMUX_BATT_CHG_I:
+		*result = adc_voltage / 1.25f;
+		break;
+	case PMIC_AMUX_BATT_NULL_I:
+	case PMIC_AMUX_THM_U:
+	case PMIC_AMUX_TBIAS_U:
+	case PMIC_AMUX_AGND_U:
+		*result = adc_voltage;
+		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) {