telelco-v3.0: Support ambient light sensor
authorKeith Packard <keithp@keithp.com>
Thu, 20 Jun 2024 06:02:30 +0000 (23:02 -0700)
committerKeith Packard <keithp@keithp.com>
Thu, 20 Jun 2024 06:02:30 +0000 (23:02 -0700)
A TEPT5700 ALS and 15k resistor from 3.3V to ground hooked to ADC10 on
PC0.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/drivers/ao_lco.h
src/drivers/ao_lco_bits.c
src/telelco-v3.0/Makefile
src/telelco-v3.0/ao_lco_v3.c
src/telelco-v3.0/ao_pins.h
src/telelco-v3.0/ao_telelco.c

index e1468b28c9aa14f754693fbd37486a3e8cb69706..47d587bb046f9076564ac57186a374a1bc7cb378 100644 (file)
@@ -56,7 +56,7 @@ extern struct ao_pad_query    ao_pad_query;   /* Last received QUERY from pad */
 #   define AO_LCO_BOX_FIRST    AO_LCO_CONTRAST
 #  endif
 # endif
-# ifdef AO_LCO_HAS_BACKLIGHT
+# ifdef AO_LCO_HAS_BACKLIGHT_UI
 #  define AO_LCO_BACKLIGHT     -1
 #  ifndef AO_LCO_BOX_FIRST
 #   define AO_LCO_BOX_FIRST    AO_LCO_BACKLIGHT
index 202e35c2be99bef4f12e497598223844aa8ec5e1..0d922d6e85d340339ca3f5c9da1f1a24b37e2403 100644 (file)
@@ -273,7 +273,7 @@ ao_lco_step_pad(int8_t dir)
                break;
        }
 #endif
-#ifdef AO_LCO_HAS_BACKLIGHT
+#ifdef AO_LCO_HAS_BACKLIGHT_UI
        case AO_LCO_BACKLIGHT: {
                int32_t backlight = ao_lco_get_backlight();
 
index 2531374b620ca1f1dd0cd7b60f460870f52b5fd1..fae076adfe5ccffc3ed1d0b2e50e2f2acb419df4 100644 (file)
@@ -48,7 +48,8 @@ ALTOS_SRC = \
        ao_timer.c \
        ao_mutex.c \
        ao_freq.c \
-       ao_adc_single_stm.c \
+       ao_adc_stm.c \
+       ao_data.c \
        ao_dma_stm.c \
        ao_spi_stm.c \
        ao_beep_stm.c \
index 701a3cbfc70457b1f75a6cdd5c48541594234d3d..2f4c1dbed26830dd27ab9a4a67c09092fd01db6c 100644 (file)
@@ -24,6 +24,7 @@
 #include <ao_st7565.h>
 #include <ao_adc_single.h>
 #include <ao_pwm.h>
+#include <limits.h>
 
 #define WIDTH  AO_ST7565_WIDTH
 #define HEIGHT AO_ST7565_HEIGHT
@@ -106,6 +107,9 @@ static uint8_t      ao_lco_event_debug;
 
 static uint8_t ao_lco_display_mutex;
 
+static uint8_t         ao_sample_data;
+static struct ao_data  ao_data_cur;
+
 static void
 _ao_center_text(int16_t x, int16_t y, const struct ao_font *font, const char *str)
 {
@@ -154,7 +158,7 @@ _ao_lco_show_contrast(void)
 }
 #endif
 
-#if AO_LCO_HAS_BACKLIGHT
+#if AO_LCO_HAS_BACKLIGHT_UI
 static void
 _ao_lco_show_backlight(void)
 {
@@ -187,13 +191,11 @@ static void
 _ao_lco_show_lco_info(void)
 {
        char            battery[7];
-       struct ao_adc   packet;
        int16_t         decivolt;
 
        ao_logo_poly(&fb, &show_transform, AO_BLACK, AO_COPY);
 
-       ao_adc_single_get(&packet);
-       decivolt = ao_battery_decivolt(packet.v_batt);
+       decivolt = ao_battery_decivolt(ao_data_cur.adc.v_batt);
        _ao_format_voltage(battery, sizeof(battery), (uint16_t) decivolt);
 
        info_y = INFO_START_Y;
@@ -238,6 +240,86 @@ _ao_lco_show_pad_info(void)
        }
 }
 
+#define AO_LCO_DIM_BACKLIGHT   (AO_LCO_MIN_BACKLIGHT + 3 * AO_LCO_BACKLIGHT_STEP)
+#define AO_AUTO_BACKLIGHT_RANGE        (AO_LCO_MAX_BACKLIGHT - AO_LCO_DIM_BACKLIGHT)
+#define AO_AUTO_BACKLIGHT_GAP  AO_ADC_MAX / 6
+
+static struct {
+       int16_t v_als;
+       int32_t backlight;
+} ao_lco_backlight_map[] = {
+       { .v_als = AO_ADC_MAX / 6, .backlight = AO_LCO_DIM_BACKLIGHT },
+       { .v_als = AO_ADC_MAX / 3, .backlight = (AO_LCO_MAX_BACKLIGHT - AO_LCO_MIN_BACKLIGHT) / 2 },
+       { .v_als = AO_ADC_MAX / 2, .backlight = AO_LCO_MAX_BACKLIGHT },
+       { .v_als = AO_ADC_MAX * 3 / 4,  .backlight = 0 },
+};
+
+#define NUM_BACKLIGHT_MAP sizeof(ao_lco_backlight_map)/sizeof(ao_lco_backlight_map[0])
+
+static unsigned ao_backlight_prev = NUM_BACKLIGHT_MAP - 1;
+
+static void
+ao_auto_backlight(int16_t als_min, int16_t als_max)
+{
+       unsigned ao_backlight;
+
+       PRINTD("ao_auto_backlight min %d max %d\n", als_min, als_max);
+       ao_backlight = ao_backlight_prev;
+       while (als_min > ao_lco_backlight_map[ao_backlight].v_als + AO_AUTO_BACKLIGHT_GAP) {
+               if (ao_backlight == NUM_BACKLIGHT_MAP - 1)
+                       break;
+               ao_backlight++;
+       }
+       while (als_max < ao_lco_backlight_map[ao_backlight].v_als - AO_AUTO_BACKLIGHT_GAP) {
+               if (ao_backlight == 0)
+                       return;
+               ao_backlight--;
+       }
+       if (ao_backlight != ao_backlight_prev)
+       {
+               PRINTD("   set backlight to %ld\n", ao_lco_backlight_map[ao_backlight].backlight);
+               ao_lco_set_backlight(ao_lco_backlight_map[ao_backlight].backlight);
+               ao_backlight_prev = ao_backlight;
+       }
+}
+
+#define AO_LCO_BACKLIGHT_INTERVAL      AO_SEC_TO_TICKS(2)
+
+static void
+ao_lco_data(void)
+{
+       AO_TICK_TYPE    backlight_tick = ao_time() + AO_LCO_BACKLIGHT_INTERVAL;
+       AO_TICK_TYPE    now;
+       int16_t         als_min = INT16_MAX;
+       int16_t         als_max = INT16_MIN;
+
+       ao_timer_set_adc_interval(AO_MS_TO_TICKS(100));
+       for (;;) {
+               ao_sleep((void *) &ao_data_head);
+
+               while (ao_sample_data != ao_data_head) {
+                       struct ao_data *ao_data;
+
+                       /* Capture a sample */
+                       ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data];
+
+                       ao_data_cur = *ao_data;
+                       if (ao_data_cur.adc.v_als < als_min)
+                               als_min = ao_data_cur.adc.v_als;
+                       if (ao_data_cur.adc.v_als > als_max)
+                               als_max = ao_data_cur.adc.v_als;
+                       ao_sample_data = ao_data_ring_next(ao_sample_data);
+               }
+               now = ao_time();
+               if ((AO_TICK_SIGNED) (backlight_tick - now) < 0) {
+                       backlight_tick = now + AO_LCO_BACKLIGHT_INTERVAL;
+                       ao_auto_backlight(als_min, als_max);
+                       als_min = INT16_MAX;
+                       als_max = INT16_MIN;
+               }
+       }
+}
+
 void
 ao_lco_show(void)
 {
@@ -249,7 +331,7 @@ ao_lco_show(void)
                _ao_lco_show_contrast();
                break;
 #endif
-#if AO_LCO_HAS_BACKLIGHT
+#if AO_LCO_HAS_BACKLIGHT_UI
        case AO_LCO_BACKLIGHT:
                _ao_lco_show_backlight();
                break;
@@ -428,6 +510,7 @@ ao_lco_display_test(void)
 
 static struct ao_task ao_lco_input_task;
 static struct ao_task ao_lco_monitor_task;
+static struct ao_task ao_lco_data_task;
 static struct ao_task ao_lco_arm_warn_task;
 static struct ao_task ao_lco_igniter_status_task;
 
@@ -525,6 +608,7 @@ void
 ao_lco_init(void)
 {
        ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor");
+       ao_add_task(&ao_lco_data_task, ao_lco_data, "lco data");
 #if DEBUG
        ao_cmd_register(&ao_lco_cmds[0]);
 #endif
index 2ed88d3ba483a046d0a14bb0bafed9d8bff4c358..b1af364fca3b9ee219fc23110e38b9be007b7718 100644 (file)
 #define AO_BUTTON_0            1
 
 #define AO_BUTTON_DRAG_SELECT  1
-#define AO_BUTTON_1_PORT       &stm_gpioc
-#define AO_BUTTON_1            0
+#define AO_BUTTON_1_PORT       &stm_gpiod
+#define AO_BUTTON_1            2
 
 #define AO_BUTTON_SPARE1               2
 #define AO_BUTTON_2_PORT       &stm_gpiob
 
 /* ADC */
 
-struct ao_adc {
-       int16_t         v_batt;
-};
-
-#define AO_ADC_DUMP(p) \
-       printf("batt: %5d\n", (p)->v_batt)
+#define AO_DATA_RING           8
 
-#define HAS_ADC_SINGLE         1
+#define HAS_ADC                        1
 #define HAS_ADC_TEMP           0
 #define HAS_BATTERY_REPORT     1
 
@@ -277,12 +272,33 @@ struct ao_adc {
 #define AO_ADC_V_BATT_PORT     (&stm_gpioa)
 #define AO_ADC_V_BATT_PIN      2
 
+#define AO_ADC_V_ALS           10
+#define AO_ADC_V_ALS_PORT      (&stm_gpioc)
+#define AO_ADC_V_ALS_PIN       0
+
 #define AO_ADC_PIN0_PORT       AO_ADC_V_BATT_PORT
 #define AO_ADC_PIN0_PIN                AO_ADC_V_BATT_PIN
 
+#define AO_ADC_PIN1_PORT       AO_ADC_V_ALS_PORT
+#define AO_ADC_PIN1_PIN                AO_ADC_V_ALS_PIN
+
 #define AO_ADC_SQ1             AO_ADC_V_BATT
+#define AO_ADC_SQ2             AO_ADC_V_ALS
 
-#define AO_NUM_ADC             1
+#define AO_NUM_ADC             2
+
+struct ao_adc {
+       union {
+               struct {
+                       int16_t         v_batt;
+                       int16_t         v_als;
+               };
+               int16_t v_vals[AO_NUM_ADC];
+       };
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("batt: %5d als %5d\n", (p)->adc.v_batt, (p)->adc.v_als)
 
 /*
  * Voltage divider on ADC battery sampler
index a8d740a9243db32ab8423c97874eb7c921f9b108..6293edd3878bdcc1bd807c8642f63b6bd96d7dd2 100644 (file)
@@ -44,7 +44,7 @@ main(void)
        ao_spi_init();
        ao_dma_init();
        ao_exti_init();
-       ao_adc_single_init();
+       ao_adc_init();
 
        ao_beep_init();
        ao_pwm_init();