From 933e12dcd3735ee19f2713b65287ede10a7e7402 Mon Sep 17 00:00:00 2001
From: moon2 <moon2protonmail@protonmail.com>
Date: Sun, 19 Nov 2023 19:07:11 +0100
Subject: [PATCH] captouch driver: add mp bindings to save/load calib

---
 components/flow3r_bsp/flow3r_bsp_ad7147.c     |  6 ++-
 components/flow3r_bsp/flow3r_bsp_ad7147.h     |  8 +++-
 components/flow3r_bsp/flow3r_bsp_captouch.c   | 32 ++++++++++++++++
 components/flow3r_bsp/flow3r_bsp_captouch.h   |  4 ++
 .../micropython/usermodule/mp_captouch.c      | 37 +++++++++++++++++++
 5 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/components/flow3r_bsp/flow3r_bsp_ad7147.c b/components/flow3r_bsp/flow3r_bsp_ad7147.c
index 31dd1e809d..4afad6ca08 100644
--- a/components/flow3r_bsp/flow3r_bsp_ad7147.c
+++ b/components/flow3r_bsp/flow3r_bsp_ad7147.c
@@ -233,12 +233,16 @@ static void _on_data(void *user, uint16_t *data, size_t len) {
     }
 
     // _sequence_request also writes the AFE registers which just got tweaked
-    if (reprogram || tweak) {
+    if (reprogram || tweak || chip->calibration_external) {
         esp_err_t ret;
         if ((ret = _sequence_request(chip, reprogram)) != ESP_OK) {
             COMPLAIN(chip, "%s: requesting next sequence failed: %s",
                      chip->name, esp_err_to_name(ret));
         }
+        if (chip->calibration_external) {
+            chip->calibration_external = false;
+            ESP_LOGI(TAG, "%s: captouch calibration updated", chip->name);
+        }
     }
 }
 
diff --git a/components/flow3r_bsp/flow3r_bsp_ad7147.h b/components/flow3r_bsp/flow3r_bsp_ad7147.h
index fa2ff2e2ee..42d8d2cbc1 100644
--- a/components/flow3r_bsp/flow3r_bsp_ad7147.h
+++ b/components/flow3r_bsp/flow3r_bsp_ad7147.h
@@ -24,13 +24,13 @@
 // 12 of them at once in a single sequence.
 typedef struct {
     // Positive AFE offset currently programmed. [0,64).
-    int8_t afe_offset;
+    volatile int8_t afe_offset;
     // Last measurement.
     uint16_t cdc;
 
     // Ambient value used for offset when checking for touch presence. Written
     // by calibration, and attempts to reach a preset calibration setpoint.
-    uint16_t amb;
+    volatile uint16_t amb;
     // Calibration samples gathered during the calibraiton process.
     uint16_t amb_meas[_AD7147_CALIB_CYCLES];
 } ad7147_channel_t;
@@ -61,8 +61,12 @@ typedef struct {
     ad7147_hw_t dev;
     bool failed;
 
+    // Request applying external calibration
     volatile bool calibration_pending;
+    // True if calibration is running or pending
     volatile bool calibration_active;
+    // Set true if external calibration is to be written to hw
+    volatile bool calibration_external;
     int8_t calibration_cycles;
 } ad7147_chip_t;
 
diff --git a/components/flow3r_bsp/flow3r_bsp_captouch.c b/components/flow3r_bsp/flow3r_bsp_captouch.c
index e5a7db385d..34b6977c5e 100644
--- a/components/flow3r_bsp/flow3r_bsp_captouch.c
+++ b/components/flow3r_bsp/flow3r_bsp_captouch.c
@@ -382,3 +382,35 @@ bool flow3r_bsp_captouch_calibrating() {
     bool top = _top.calibration_pending || _top.calibration_active;
     return bot || top;
 }
+
+void flow3r_bsp_captouch_get_calibration_data(int32_t *data) {
+    while (flow3r_bsp_captouch_calibrating()) {
+    };
+    for (uint8_t i = 0; i < 13; i++) {
+        data[2 * i] = _top.channels[i].afe_offset;
+        data[2 * i + 1] = _top.channels[i].amb;
+        data[2 * i + 26] = _bot.channels[i].afe_offset;
+        data[2 * i + 27] = _bot.channels[i].amb;
+    }
+}
+
+static uint16_t amb_limit(int32_t data) {
+    return data > 65535 ? 65535 : (data < 0 ? 0 : data);
+}
+
+static uint8_t afe_limit(int32_t data) {
+    return data > 63 ? 63 : (data < 0 ? 0 : data);
+}
+
+void flow3r_bsp_captouch_set_calibration_data(int32_t *data) {
+    while (flow3r_bsp_captouch_calibrating()) {
+    };
+    for (uint8_t i = 0; i < 13; i++) {
+        _top.channels[i].afe_offset = afe_limit(data[2 * i]);
+        _top.channels[i].amb = amb_limit(data[2 * i + 1]);
+        _bot.channels[i].afe_offset = afe_limit(data[2 * i + 26]);
+        _bot.channels[i].amb = amb_limit(data[2 * i + 27]);
+    }
+    _top.calibration_external = true;
+    _bot.calibration_external = true;
+}
diff --git a/components/flow3r_bsp/flow3r_bsp_captouch.h b/components/flow3r_bsp/flow3r_bsp_captouch.h
index 71c12922ec..57dc0e1d55 100644
--- a/components/flow3r_bsp/flow3r_bsp_captouch.h
+++ b/components/flow3r_bsp/flow3r_bsp_captouch.h
@@ -84,3 +84,7 @@ void flow3r_bsp_captouch_calibrate();
 
 // Returns true if captouch is currently calibrating.
 bool flow3r_bsp_captouch_calibrating();
+
+// Set/get calibration data. data[] should be at least 52 entries long.
+void flow3r_bsp_captouch_get_calibration_data(int32_t *data);
+void flow3r_bsp_captouch_set_calibration_data(int32_t *data);
diff --git a/components/micropython/usermodule/mp_captouch.c b/components/micropython/usermodule/mp_captouch.c
index b51c86dfcf..1cc0757a79 100644
--- a/components/micropython/usermodule/mp_captouch.c
+++ b/components/micropython/usermodule/mp_captouch.c
@@ -1,6 +1,7 @@
 #include "py/builtin.h"
 #include "py/runtime.h"
 
+#include "flow3r_bsp_captouch.h"
 #include "st3m_captouch.h"
 
 #include <string.h>
@@ -181,6 +182,38 @@ STATIC mp_obj_t mp_captouch_refresh_events(void) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_captouch_refresh_events_obj,
                                  mp_captouch_refresh_events);
 
+STATIC mp_obj_t mp_captouch_calibration_get_data(void) {
+    int32_t data[52];
+    flow3r_bsp_captouch_get_calibration_data(data);
+    mp_obj_t items[52];
+    for (uint8_t i = 0; i < 52; i++) {
+        items[i] = mp_obj_new_int(data[i]);
+    }
+    return mp_obj_new_tuple(52, items);
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_captouch_calibration_get_data_obj,
+                                 mp_captouch_calibration_get_data);
+
+STATIC mp_obj_t mp_captouch_calibration_set_data(mp_obj_t mp_data) {
+    int32_t data[52];
+    mp_obj_iter_buf_t iter_buf;
+    mp_obj_t iterable = mp_getiter(mp_data, &iter_buf);
+    mp_obj_t item;
+    uint8_t i = 0;
+    while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
+        data[i] = mp_obj_get_int(item);
+        i++;
+        if (i == 52) break;
+    }
+    // if(i != 52) TODO: Throw error? Maybe?
+    flow3r_bsp_captouch_set_calibration_data(data);
+    return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_captouch_calibration_set_data_obj,
+                                 mp_captouch_calibration_set_data);
+
 STATIC const mp_rom_map_elem_t globals_table[] = {
     { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_captouch_read_obj) },
     { MP_ROM_QSTR(MP_QSTR_refresh_events),
@@ -189,6 +222,10 @@ STATIC const mp_rom_map_elem_t globals_table[] = {
       MP_ROM_PTR(&mp_captouch_calibration_active_obj) },
     { MP_ROM_QSTR(MP_QSTR_calibration_request),
       MP_ROM_PTR(&mp_captouch_calibration_request_obj) },
+    { MP_ROM_QSTR(MP_QSTR_calibration_get_data),
+      MP_ROM_PTR(&mp_captouch_calibration_get_data_obj) },
+    { MP_ROM_QSTR(MP_QSTR_calibration_set_data),
+      MP_ROM_PTR(&mp_captouch_calibration_set_data_obj) },
 };
 
 STATIC MP_DEFINE_CONST_DICT(globals, globals_table);
-- 
GitLab