From 639031fc38926aacc89a60e317e3a7d6a470b2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 25 Feb 2018 00:03:05 +0100 Subject: [PATCH 1/5] added template install script and utouch config --- units/template/install.sh | 23 ++++ units/touch/_touch_api.c | 11 ++ units/touch/_touch_init.c | 56 ++++++++++ units/touch/_touch_internal.h | 57 ++++++++++ units/touch/_touch_settings.c | 205 ++++++++++++++++++++++++++++++++++ units/touch/unit_touch.c | 56 ++++++++++ units/touch/unit_touch.h | 16 +++ 7 files changed, 424 insertions(+) create mode 100755 units/template/install.sh create mode 100644 units/touch/_touch_api.c create mode 100644 units/touch/_touch_init.c create mode 100644 units/touch/_touch_internal.h create mode 100644 units/touch/_touch_settings.c create mode 100644 units/touch/unit_touch.c create mode 100644 units/touch/unit_touch.h diff --git a/units/template/install.sh b/units/template/install.sh new file mode 100755 index 0000000..7feac33 --- /dev/null +++ b/units/template/install.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +echo "Enter unit type identifier (empty to cancel):" +read x + +if [ -e $x ]; then + exit; +fi + +xl="${x,,}" +xu="${x^^}" + +for f in *.h; do mv -- "$f" "${f//tpl/$xl}"; done +for f in *.c; do mv -- "$f" "${f//tpl/$xl}"; done + +sed "s/tpl/$xl/" -i *.h +sed "s/TPL/$xu/" -i *.h +sed "s/tpl/$xl/" -i *.c +sed "s/TPL/$xu/" -i *.c + +echo "Unit $xu set up completed. Removing installer.." +rm '!README.TXT' +rm $0 diff --git a/units/touch/_touch_api.c b/units/touch/_touch_api.c new file mode 100644 index 0000000..5eec0e4 --- /dev/null +++ b/units/touch/_touch_api.c @@ -0,0 +1,11 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#include "platform.h" +#include "unit_base.h" +#include "unit_touch.h" + +#define TOUCH_INTERNAL +#include "_touch_internal.h" + diff --git a/units/touch/_touch_init.c b/units/touch/_touch_init.c new file mode 100644 index 0000000..74221dd --- /dev/null +++ b/units/touch/_touch_init.c @@ -0,0 +1,56 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#include "platform.h" +#include "unit_base.h" + +#define TOUCH_INTERNAL +#include "_touch_internal.h" + +/** Allocate data structure and set defaults */ +error_t UTOUCH_preInit(Unit *unit) +{ + struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv)); + if (priv == NULL) return E_OUT_OF_MEM; + + priv->cfg.charge_time = 2; + priv->cfg.drain_time = 2; + priv->cfg.spread_deviation = 0; + priv->cfg.ss_presc = 1; + priv->cfg.pg_presc = 32; + priv->cfg.sense_timeout = 7; + memset(priv->cfg.group_scaps, 0, 8); + memset(priv->cfg.group_channels, 0, 8); + + return E_SUCCESS; +} + +/** Finalize unit set-up */ +error_t UTOUCH_init(Unit *unit) +{ + bool suc = true; + struct priv *priv = unit->data; + + // + + return E_SUCCESS; +} + + +/** Tear down the unit */ +void UTOUCH_deInit(Unit *unit) +{ + struct priv *priv = unit->data; + + // de-init peripherals + if (unit->status == E_SUCCESS ) { + // + } + + // Release all resources, deinit pins + rsc_teardown(unit); + + // Free memory + free_ck(unit->data); +} diff --git a/units/touch/_touch_internal.h b/units/touch/_touch_internal.h new file mode 100644 index 0000000..e4c865d --- /dev/null +++ b/units/touch/_touch_internal.h @@ -0,0 +1,57 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#ifndef GEX_F072_TOUCH_INTERNAL_H +#define GEX_F072_TOUCH_INTERNAL_H + +#ifndef TOUCH_INTERNAL +#error bad include! +#endif + +#include "unit_base.h" + +/** Private data structure */ +struct priv { + // settings + struct { + uint8_t charge_time; // 1-16 -> 0..15 + uint8_t drain_time; // 1-16 -> 0..15 + uint8_t spread_deviation; // 1-128, 0=off ... 0-127, 0 sets 0 to SSE + uint8_t ss_presc; // 1-2 -> 0..1 + uint8_t pg_presc; // 1,2,4,8,16,32,64,128 -> 0..7 when writing to the periph + uint8_t sense_timeout; // 1-7 -> 0..6 hex when writing to the periph + // the schmitts must be disabled on all used channels, restored to 0xFFFF on deinit + uint8_t group_scaps[8]; + uint8_t group_channels[8]; + } cfg; + + // internal state +}; + +/** Allocate data structure and set defaults */ +error_t UTOUCH_preInit(Unit *unit); + +/** Load from a binary buffer stored in Flash */ +void UTOUCH_loadBinary(Unit *unit, PayloadParser *pp); + +/** Write to a binary buffer for storing in Flash */ +void UTOUCH_writeBinary(Unit *unit, PayloadBuilder *pb); + +// ------------------------------------------------------------------------ + +/** Parse a key-value pair from the INI file */ +error_t UTOUCH_loadIni(Unit *unit, const char *key, const char *value); + +/** Generate INI file section for the unit */ +void UTOUCH_writeIni(Unit *unit, IniWriter *iw); + +// ------------------------------------------------------------------------ + +/** Finalize unit set-up */ +error_t UTOUCH_init(Unit *unit); + +/** Tear down the unit */ +void UTOUCH_deInit(Unit *unit); + +#endif //GEX_F072_TOUCH_INTERNAL_H diff --git a/units/touch/_touch_settings.c b/units/touch/_touch_settings.c new file mode 100644 index 0000000..3aac527 --- /dev/null +++ b/units/touch/_touch_settings.c @@ -0,0 +1,205 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#include "platform.h" +#include "unit_base.h" + +#define TOUCH_INTERNAL +#include "_touch_internal.h" + +// some channels are mapped to nonexistent ports, so just ignore them - clutters the config +#define HAVE_CH7 0 +#define HAVE_CH8 0 + +/** Load from a binary buffer stored in Flash */ +void UTOUCH_loadBinary(Unit *unit, PayloadParser *pp) +{ + struct priv *priv = unit->data; + + uint8_t version = pp_u8(pp); + (void)version; + + priv->cfg.charge_time = pp_u8(pp); + priv->cfg.drain_time = pp_u8(pp); + priv->cfg.spread_deviation = pp_u8(pp); + priv->cfg.ss_presc = pp_u8(pp); + priv->cfg.pg_presc = pp_u8(pp); + priv->cfg.sense_timeout = pp_u8(pp); + pp_buf(pp, priv->cfg.group_scaps, 8); + pp_buf(pp, priv->cfg.group_channels, 8); +} + +/** Write to a binary buffer for storing in Flash */ +void UTOUCH_writeBinary(Unit *unit, PayloadBuilder *pb) +{ + struct priv *priv = unit->data; + + pb_u8(pb, 0); // version + + pb_u8(pb, priv->cfg.charge_time); + pb_u8(pb, priv->cfg.drain_time); + pb_u8(pb, priv->cfg.spread_deviation); + pb_u8(pb, priv->cfg.ss_presc); + pb_u8(pb, priv->cfg.pg_presc); + pb_u8(pb, priv->cfg.sense_timeout); + pb_buf(pb, priv->cfg.group_scaps, 8); + pb_buf(pb, priv->cfg.group_channels, 8); +} + +// ------------------------------------------------------------------------ + +/** Parse a key-value pair from the INI file */ +error_t UTOUCH_loadIni(Unit *unit, const char *key, const char *value) +{ + bool suc = true; + struct priv *priv = unit->data; + + if (streq(key, "charge-time")) { + priv->cfg.charge_time = cfg_u8_parse(value, &suc); + } + else if (streq(key, "drain-time")) { + priv->cfg.drain_time = cfg_u8_parse(value, &suc); + } + else if (streq(key, "ss-deviation")) { + priv->cfg.spread_deviation = cfg_u8_parse(value, &suc); + } + else if (streq(key, "ss-clock-prediv")) { + priv->cfg.ss_presc = cfg_u8_parse(value, &suc); + } + else if (streq(key, "pg-clock-prediv")) { + priv->cfg.pg_presc = cfg_u8_parse(value, &suc); + } + else if (streq(key, "sense-timeout")) { + priv->cfg.sense_timeout = cfg_u8_parse(value, &suc); + } + + else if (streq(key, "g1_cap")) { + priv->cfg.group_scaps[0] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g2_cap")) { + priv->cfg.group_scaps[1] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g3_cap")) { + priv->cfg.group_scaps[2] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g4_cap")) { + priv->cfg.group_scaps[3] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g5_cap")) { + priv->cfg.group_scaps[4] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g6_cap")) { + priv->cfg.group_scaps[5] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#if HAVE_CH7 + else if (streq(key, "g7_cap")) { + priv->cfg.group_scaps[6] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#endif +#if HAVE_CH8 + else if (streq(key, "g8_cap")) { + priv->cfg.group_scaps[7] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#endif + + else if (streq(key, "g1_ch")) { + priv->cfg.group_channels[0] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g2_ch")) { + priv->cfg.group_channels[1] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g3_ch")) { + priv->cfg.group_channels[2] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g4_ch")) { + priv->cfg.group_channels[3] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g5_ch")) { + priv->cfg.group_channels[4] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g6_ch")) { + priv->cfg.group_channels[5] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#if HAVE_CH7 + else if (streq(key, "g7_ch")) { + priv->cfg.group_channels[6] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#endif +#if HAVE_CH8 + else if (streq(key, "g8_ch")) { + priv->cfg.group_channels[7] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#endif + + else { + return E_BAD_KEY; + } + + if (!suc) return E_BAD_VALUE; + return E_SUCCESS; +} + +/** Generate INI file section for the unit */ +void UTOUCH_writeIni(Unit *unit, IniWriter *iw) +{ + struct priv *priv = unit->data; + + iw_comment(iw, "This unit utilizes the touch sensing controller."); + iw_comment(iw, "See the reference manual for details about its function."); + iw_cmt_newline(iw); + + iw_comment(iw, "Pulse generator clock prescaller (1,2,4,...,128)"); + iw_entry(iw, "pg-clock-prediv", "%d", (int)priv->cfg.ss_presc); + iw_comment(iw, "Sense pad charging time (1-16)"); + iw_entry(iw, "charge-time", "%d", (int)priv->cfg.charge_time); + iw_comment(iw, "Charge transfer time (1-16)"); + iw_entry(iw, "drain-time", "%d", (int)priv->cfg.drain_time); + iw_comment(iw, "Spread spectrum max deviation (0-128,0=off)"); + iw_entry(iw, "ss-deviation", "%d", (int)priv->cfg.spread_deviation); + iw_comment(iw, "Spreading clock prescaller (1,2)"); + iw_entry(iw, "ss-clock-prediv", "%d", (int)priv->cfg.ss_presc); + iw_comment(iw, "Measurement timeout (1-7)"); + iw_entry(iw, "sense-timeout", "%d", (int)priv->cfg.sense_timeout); + + iw_cmt_newline(iw); + iw_comment(iw, "Each used group must have 1 sampling capacitor and 1-3 channels."); + iw_comment(iw, "Channels are numbered 1,2,3,4"); + iw_cmt_newline(iw); + + iw_comment(iw, "Group 1: A0,A1,A2,A3"); + iw_entry(iw, "g1_cap", cfg_pinmask_encode(priv->cfg.group_scaps[0], unit_tmp512, true)); + iw_entry(iw, "g1_ch", cfg_pinmask_encode(priv->cfg.group_channels[0], unit_tmp512, true)); + + iw_comment(iw, "Group 2: A4,A5,A6,A7"); + iw_entry(iw, "g2_cap", cfg_pinmask_encode(priv->cfg.group_scaps[1], unit_tmp512, true)); + iw_entry(iw, "g2_ch", cfg_pinmask_encode(priv->cfg.group_channels[1], unit_tmp512, true)); + + iw_comment(iw, "Group 3: C5,B0,B1,B2"); + iw_entry(iw, "g3_cap", cfg_pinmask_encode(priv->cfg.group_scaps[2], unit_tmp512, true)); + iw_entry(iw, "g3_ch", cfg_pinmask_encode(priv->cfg.group_channels[2], unit_tmp512, true)); + + iw_comment(iw, "Group 4: A9,A10,A11,A12"); + iw_entry(iw, "g4_cap", cfg_pinmask_encode(priv->cfg.group_scaps[3], unit_tmp512, true)); + iw_entry(iw, "g4_ch", cfg_pinmask_encode(priv->cfg.group_channels[3], unit_tmp512, true)); + + iw_comment(iw, "Group 5: B3,B4,B6,B7"); + iw_entry(iw, "g5_cap", cfg_pinmask_encode(priv->cfg.group_scaps[4], unit_tmp512, true)); + iw_entry(iw, "g5_ch", cfg_pinmask_encode(priv->cfg.group_channels[4], unit_tmp512, true)); + + iw_comment(iw, "Group 6: B11,B12,B13,B14"); + iw_entry(iw, "g6_cap", cfg_pinmask_encode(priv->cfg.group_scaps[5], unit_tmp512, true)); + iw_entry(iw, "g6_ch", cfg_pinmask_encode(priv->cfg.group_channels[5], unit_tmp512, true)); + +#if HAVE_CH7 + iw_comment(iw, "E2,E3,E4,E5"); + iw_entry(iw, "g7_cap", cfg_pinmask_encode(priv->cfg.group_scaps[6], unit_tmp512, true)); + iw_entry(iw, "g7_ch", cfg_pinmask_encode(priv->cfg.group_channels[6], unit_tmp512, true)); +#endif +#if HAVE_CH8 + iw_comment(iw, "D12,D13,D14,D15"); + iw_entry(iw, "g8_cap", cfg_pinmask_encode(priv->cfg.group_scaps[7], unit_tmp512, true)); + iw_entry(iw, "g8_ch", cfg_pinmask_encode(priv->cfg.group_channels[7], unit_tmp512, true)); +#endif +} + diff --git a/units/touch/unit_touch.c b/units/touch/unit_touch.c new file mode 100644 index 0000000..59cd19c --- /dev/null +++ b/units/touch/unit_touch.c @@ -0,0 +1,56 @@ +// +// Created by MightyPork on 2017/11/25. +// + +#include "unit_base.h" +#include "unit_touch.h" + +#define TOUCH_INTERNAL +#include "_touch_internal.h" + +// ------------------------------------------------------------------------ + +enum TouchCmd_ { + // +}; + +/** Handle a request message */ +static error_t UTOUCH_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp) +{ + switch (command) { + default: + return E_UNKNOWN_COMMAND; + } +} + +// ------------------------------------------------------------------------ + +/** + * Handle update-tick (if configured in init) + * + * @param unit + */ +static void UTOUCH_updateTick(Unit *unit) +{ + // +} + +// ------------------------------------------------------------------------ + +/** Unit template */ +const UnitDriver UNIT_TOUCH = { + .name = "TOUCH", + .description = "Capacitive touch sensing", + // Settings + .preInit = UTOUCH_preInit, + .cfgLoadBinary = UTOUCH_loadBinary, + .cfgWriteBinary = UTOUCH_writeBinary, + .cfgLoadIni = UTOUCH_loadIni, + .cfgWriteIni = UTOUCH_writeIni, + // Init + .init = UTOUCH_init, + .deInit = UTOUCH_deInit, + // Function + .handleRequest = UTOUCH_handleRequest, + .updateTick = UTOUCH_updateTick, +}; diff --git a/units/touch/unit_touch.h b/units/touch/unit_touch.h new file mode 100644 index 0000000..dc3b2fa --- /dev/null +++ b/units/touch/unit_touch.h @@ -0,0 +1,16 @@ +// +// Created by MightyPork on 2017/11/25. +// +// Digital input unit; single or multiple pin read access on one port (A-F) +// + +#ifndef U_TOUCH_H +#define U_TOUCH_H + +#include "unit.h" + +extern const UnitDriver UNIT_TOUCH; + +// UU_ prototypes + +#endif //U_TOUCH_H From 1f2d346e23b2a0988c7e03409a204ba645ac662f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 25 Feb 2018 13:37:57 +0100 Subject: [PATCH 2/5] tsc ini structure + debug msgs --- framework/resources.c | 19 ++--- framework/rsc_enum.h | 6 +- gex.mk | 1 + platform/hw_utils.c | 37 ++++++++- platform/hw_utils.h | 3 + platform/plat_compat.h | 2 +- platform/platform.c | 8 +- units/touch/_touch_init.c | 71 ++++++++++++++++- units/touch/_touch_internal.h | 8 +- units/touch/_touch_settings.c | 142 +++++++++++----------------------- units/touch/unit_touch.c | 2 +- 11 files changed, 184 insertions(+), 115 deletions(-) diff --git a/framework/resources.c b/framework/resources.c index 5422c71..8c05176 100644 --- a/framework/resources.c +++ b/framework/resources.c @@ -33,12 +33,6 @@ const char * rsc_get_name(Resource rsc) // we assume the returned value is not stored anywhere // and is directly used in a sprintf call, hence a static buffer is OK to use - if (rsc >= R_EXTI0 && rsc <= R_EXTI15) { - uint8_t index = rsc - R_EXTI0; - SNPRINTF(gpionamebuf, 8, "EXTI%d", index); - return gpionamebuf; - } - // R_PA0 is 0 if (rsc <= R_PF15) { // we assume the returned value is not stored anywhere @@ -48,6 +42,12 @@ const char * rsc_get_name(Resource rsc) return gpionamebuf; } + if (rsc >= R_EXTI0 && rsc <= R_EXTI15) { + uint8_t index = rsc - R_EXTI0; + SNPRINTF(gpionamebuf, 8, "EXTI%d", index); + return gpionamebuf; + } + return rsc_names[rsc - R_EXTI15 - 1]; } @@ -85,11 +85,12 @@ const char * rsc_get_owner_name(Resource rsc) void rsc_init_registry(void) { - for(uint32_t i = 0; i < RSCMAP_LEN; i++) { - UNIT_PLATFORM.resources[i] = global_rscmap[i] = 0xFF; - } + memset(UNIT_PLATFORM.resources, 0xFF, RSCMAP_LEN); + memset(global_rscmap, 0xFF, RSCMAP_LEN); rsc_initialized = true; + + rsc_dbg("Total %d hw resources, bitmap has %d bytes.", RESOURCE_COUNT, RSCMAP_LEN); } diff --git a/framework/rsc_enum.h b/framework/rsc_enum.h index 4dae01b..7a1957e 100644 --- a/framework/rsc_enum.h +++ b/framework/rsc_enum.h @@ -13,6 +13,7 @@ X(I2C1) X(I2C2) X(I2C3) \ X(ADC1) X(ADC2) X(ADC3) X(ADC4) \ X(DAC1) X(DAC2) \ + X(TSC) \ X(USART1) X(USART2) X(USART3) X(USART4) X(USART5) X(USART6) \ X(TIM1) X(TIM2) X(TIM3) X(TIM4) X(TIM5) \ X(TIM6) X(TIM7) X(TIM8) X(TIM9) X(TIM10) X(TIM11) X(TIM12) X(TIM13) X(TIM14) \ @@ -24,7 +25,6 @@ // X(I2S1) X(I2S2) X(I2S3) // X(OPAMP1) X(OPAMP2) X(OPAMP3) X(OPAMP4) // X(CAN1) X(CAN2) -// X(TSC) // X(DCMI) // X(ETH) // X(FSMC) @@ -59,8 +59,12 @@ typedef enum hw_resource Resource; /** Enum of all resources */ enum hw_resource { #define X(res_name) R_##res_name, + // GPIO are at the beginning, because some units use the constants in their config to represent + // selected pins and those must not change with adding more stuff to the main list XX_RESOURCES_GPIO + // EXTIs (same like GPIOs) have dynamically generated labels to save rom space. Must be contiguous. XX_RESOURCES_EXTI + // All the rest ... XX_RESOURCES #undef X R_NONE, diff --git a/gex.mk b/gex.mk index a6d40c6..2066ea0 100644 --- a/gex.mk +++ b/gex.mk @@ -16,6 +16,7 @@ GEX_SRC_DIR = \ User/units/adc \ User/units/sipo \ User/units/fcap \ + User/units/touch \ User/TinyFrame \ User/CWPack \ User/tasks diff --git a/platform/hw_utils.c b/platform/hw_utils.c index 7a8fcf1..abe745c 100644 --- a/platform/hw_utils.c +++ b/platform/hw_utils.c @@ -3,7 +3,6 @@ // #include "platform.h" -#include "utils/avrlibc.h" #include "hw_utils.h" /** Convert pin number to LL bitfield */ @@ -131,6 +130,30 @@ error_t hw_configure_gpio_af(char port_name, uint8_t pin_num, uint32_t ll_af) return E_SUCCESS; } +/** Configure a pin to alternate function */ +error_t hw_configure_gpiorsc_af(Resource rsc, uint32_t ll_af) +{ +#if PLAT_NO_AFNUM + trap("Illegal call to hw_configure_gpio_af() on this platform"); +#else + + bool suc = true; + GPIO_TypeDef *port; + uint32_t ll_pin; + suc = hw_pinrsc2ll(rsc, &port, &ll_pin); + if (!suc) return E_BAD_CONFIG; + + if (ll_pin & 0xFF) + LL_GPIO_SetAFPin_0_7(port, ll_pin, ll_af); + else + LL_GPIO_SetAFPin_8_15(port, ll_pin, ll_af); + + LL_GPIO_SetPinMode(port, ll_pin, LL_GPIO_MODE_ALTERNATE); + +#endif + return E_SUCCESS; +} + /** Configure pins using sparse map */ error_t hw_configure_sparse_pins(char port_name, uint16_t mask, GPIO_TypeDef **port_dest, uint32_t ll_mode, uint32_t ll_otype) @@ -288,6 +311,12 @@ void hw_periph_clock_enable(void *periph) #ifdef DAC2 else if (periph == DAC2) __HAL_RCC_DAC2_CLK_ENABLE(); #endif + + // --- TSC --- +#ifdef TSC + else if (periph == TSC) __HAL_RCC_TSC_CLK_ENABLE(); +#endif + else { dbg("Periph 0x%p missing in hw clock enable func", periph); trap("BUG"); @@ -393,6 +422,12 @@ void hw_periph_clock_disable(void *periph) #ifdef DAC2 else if (periph == DAC2) __HAL_RCC_DAC2_CLK_DISABLE(); #endif + + // --- TSC --- +#ifdef TSC + else if (periph == TSC) __HAL_RCC_TSC_CLK_DISABLE(); +#endif + else { dbg("Periph 0x%p missing in hw clock disable func", periph); trap("BUG"); diff --git a/platform/hw_utils.h b/platform/hw_utils.h index 5f9d358..e91fa48 100644 --- a/platform/hw_utils.h +++ b/platform/hw_utils.h @@ -88,6 +88,9 @@ void hw_deinit_unit_pins(Unit *unit); */ error_t hw_configure_gpio_af(char port_name, uint8_t pin_num, uint32_t ll_af) __attribute__((warn_unused_result)); +/** Configure a pin to alternate function via rsc */ +error_t hw_configure_gpiorsc_af(Resource rsc, uint32_t ll_af) __attribute__((warn_unused_result)); + /** * Configure multiple pins using the bitmap pattern * diff --git a/platform/plat_compat.h b/platform/plat_compat.h index b2dedea..74f1025 100644 --- a/platform/plat_compat.h +++ b/platform/plat_compat.h @@ -21,7 +21,7 @@ #endif // 180 is normally enough if not doing extensive debug logging -#define TSK_STACK_MSG 200 // TF message handler task stack size (all unit commands run on this thread) +#define TSK_STACK_MSG 220 // TF message handler task stack size (all unit commands run on this thread) #define TSK_STACK_IDLE 64 //configMINIMAL_STACK_SIZE #define TSK_STACK_TIMERS 64 //configTIMER_TASK_STACK_DEPTH diff --git a/platform/platform.c b/platform/platform.c index 27b73e2..678cd34 100644 --- a/platform/platform.c +++ b/platform/platform.c @@ -2,7 +2,6 @@ // Created by MightyPork on 2017/11/26. // -#include #include "platform.h" #include "usbd_core.h" #include "USB/usb_device.h" @@ -19,6 +18,8 @@ #include "units/usart/unit_usart.h" #include "units/spi/unit_spi.h" #include "units/sipo/unit_sipo.h" +#include "units/fcap/unit_fcap.h" +#include "units/touch/unit_touch.h" #include "hw_utils.h" void plat_init_resources(void) @@ -90,6 +91,7 @@ void plat_init_resources(void) ureg_add_type(&UNIT_ADC); ureg_add_type(&UNIT_SIPO); ureg_add_type(&UNIT_FCAP); + ureg_add_type(&UNIT_TOUCH); // Free all present resources { @@ -98,7 +100,7 @@ void plat_init_resources(void) // rsc_free_range(NULL, R_COMP1, R_COMP2); rsc_free(NULL, R_DAC1); // rsc_free(NULL, R_HDMI_CEC); -// rsc_free(NULL, R_TSC); + rsc_free(NULL, R_TSC); rsc_free_range(NULL, R_I2C1, R_I2C2); // rsc_free_range(NULL, R_I2S1, R_I2S2); rsc_free_range(NULL, R_SPI1, R_SPI2); @@ -154,7 +156,7 @@ void plat_init_resources(void) rsc_free_range(NULL, R_TIM1, R_TIM4); rsc_free_range(NULL, R_TIM6, R_TIM8); rsc_free_range(NULL, R_TIM15, R_TIM17); -// rsc_free(NULL, R_TSC); + rsc_free(NULL, R_TSC); rsc_free_range(NULL, R_USART1, R_USART5); rsc_free_range(NULL, R_PA0, R_PA15); diff --git a/units/touch/_touch_init.c b/units/touch/_touch_init.c index 74221dd..af00611 100644 --- a/units/touch/_touch_init.c +++ b/units/touch/_touch_init.c @@ -2,6 +2,7 @@ // Created by MightyPork on 2018/02/03. // +#include #include "platform.h" #include "unit_base.h" @@ -32,7 +33,70 @@ error_t UTOUCH_init(Unit *unit) bool suc = true; struct priv *priv = unit->data; - // + TRY(rsc_claim(unit, R_TSC)); + + // enable clock + hw_periph_clock_enable(TSC); + + for (int gi = 0; gi < 8; gi++) { + const uint8_t cap = priv->cfg.group_scaps[gi]; + const uint8_t ch = priv->cfg.group_channels[gi]; + + if (cap == 0) { + if (ch != 0) { + dbg("TSC group %d has no cap!", (int)(gi+1)); + return E_BAD_CONFIG; + } + continue; + } + + if (ch == 0) continue; // if no channels, don't bother setting up anything + + if (cap != 2 && cap != 4 && cap != 8 && cap != 16) { + dbg("TSC group %d has more than 1 cap!", (int)(gi+1)); + return E_BAD_CONFIG; + } + + if (cap & ch) { + dbg("TSC pin can't be both channel and cap! (gpr %d)", (int)(gi+1)); + return E_BAD_CONFIG; + } + + int chnum = 0; + for (int pi = 0; pi < 4; pi++) { + // pin numbers are 1-based in the config + const bool iscap = 0 != (cap & (2 << pi)); + const bool isch = 0 != (ch & (2 << pi)); + + if (iscap || isch) { + Resource r = utouch_group_rscs[gi][pi]; + TRY(rsc_claim(unit, r)); + // 7 and 8 (1-based) use AF1, else AF3 + TRY(hw_configure_gpiorsc_af(r, gi >= 6 ? LL_GPIO_AF_1 : LL_GPIO_AF_3)); + + if (iscap) dbg("TSC *cap @ %s", rsc_get_name(r)); + else dbg("TSC -ch @ %s", rsc_get_name(r)); + } + + // Sampling cap + if (iscap) { + TSC->IOSCR |= (cap>>1) << (gi*4); + } + + // channels are configured individually when read. + // we prepare bitmaps to use for the read groups (all can be read in at most 3 steps) + if (isch) { + priv->channels_phase[chnum] |= 1 << (gi*4+pi); + priv->pgen_phase[chnum] |= 1 << gi; + chnum++; + } + } + } + + dbg("TSC phases:"); + for (int i = 0; i < 3; i++) { + dbg(" %d: ch %08"PRIx32", g %02"PRIx32, i+1, priv->channels_phase[i], (uint32_t)priv->pgen_phase[i]); + } return E_SUCCESS; } @@ -45,7 +109,10 @@ void UTOUCH_deInit(Unit *unit) // de-init peripherals if (unit->status == E_SUCCESS ) { - // + hw_periph_clock_disable(TSC); + // clear all registers to their default values + __HAL_RCC_TSC_FORCE_RESET(); + __HAL_RCC_TSC_RELEASE_RESET(); } // Release all resources, deinit pins diff --git a/units/touch/_touch_internal.h b/units/touch/_touch_internal.h index e4c865d..9ce0e40 100644 --- a/units/touch/_touch_internal.h +++ b/units/touch/_touch_internal.h @@ -26,9 +26,15 @@ struct priv { uint8_t group_channels[8]; } cfg; - // internal state + uint8_t next_phase; + uint32_t channels_phase[3]; + uint8_t pgen_phase[3]; + uint16_t readouts[32]; }; +extern const char *utouch_group_labels[8]; +extern const Resource utouch_group_rscs[8][4]; + /** Allocate data structure and set defaults */ error_t UTOUCH_preInit(Unit *unit); diff --git a/units/touch/_touch_settings.c b/units/touch/_touch_settings.c index 3aac527..def2f96 100644 --- a/units/touch/_touch_settings.c +++ b/units/touch/_touch_settings.c @@ -8,9 +8,27 @@ #define TOUCH_INTERNAL #include "_touch_internal.h" -// some channels are mapped to nonexistent ports, so just ignore them - clutters the config -#define HAVE_CH7 0 -#define HAVE_CH8 0 +const char *utouch_group_labels[8] = { + "1:A0, 2:A1, 3:A2, 4:A3", + "1:A4, 2:A5, 3:A6, 4:A7", + "1:C5, 2:B0, 3:B1, 4:B2", + "1:A9, 2:A10, 3:A11, 4:A12", + "1:B3, 2:B4, 3:B6, 4:B7", + "1:B11, 2:B12, 3:B13, 4:B14", + "1:E2, 2:E3, 3:E4, 4:E5", + "1:D12, 2:D13, 3:D14, 4:D15", +}; + +const Resource utouch_group_rscs[8][4] = { + {R_PA0, R_PA1, R_PA2, R_PA3}, + {R_PA4, R_PA5, R_PA6, R_PA7}, + {R_PC5, R_PB0, R_PB1, R_PB2}, + {R_PA9, R_PA10, R_PA11, R_PA12}, + {R_PB3, R_PB4, R_PB6, R_PB7}, + {R_PB11, R_PB12, R_PB13, R_PB14}, + {R_PE2, R_PE3, R_PE4, R_PE5}, + {R_PD12, R_PD13, R_PD14, R_PD15}, +}; /** Load from a binary buffer stored in Flash */ void UTOUCH_loadBinary(Unit *unit, PayloadParser *pp) @@ -73,69 +91,27 @@ error_t UTOUCH_loadIni(Unit *unit, const char *key, const char *value) else if (streq(key, "sense-timeout")) { priv->cfg.sense_timeout = cfg_u8_parse(value, &suc); } - - else if (streq(key, "g1_cap")) { - priv->cfg.group_scaps[0] = (uint8_t) cfg_pinmask_parse(value, &suc); - } - else if (streq(key, "g2_cap")) { - priv->cfg.group_scaps[1] = (uint8_t) cfg_pinmask_parse(value, &suc); - } - else if (streq(key, "g3_cap")) { - priv->cfg.group_scaps[2] = (uint8_t) cfg_pinmask_parse(value, &suc); - } - else if (streq(key, "g4_cap")) { - priv->cfg.group_scaps[3] = (uint8_t) cfg_pinmask_parse(value, &suc); - } - else if (streq(key, "g5_cap")) { - priv->cfg.group_scaps[4] = (uint8_t) cfg_pinmask_parse(value, &suc); - } - else if (streq(key, "g6_cap")) { - priv->cfg.group_scaps[5] = (uint8_t) cfg_pinmask_parse(value, &suc); - } -#if HAVE_CH7 - else if (streq(key, "g7_cap")) { - priv->cfg.group_scaps[6] = (uint8_t) cfg_pinmask_parse(value, &suc); - } -#endif -#if HAVE_CH8 - else if (streq(key, "g8_cap")) { - priv->cfg.group_scaps[7] = (uint8_t) cfg_pinmask_parse(value, &suc); - } -#endif - - else if (streq(key, "g1_ch")) { - priv->cfg.group_channels[0] = (uint8_t) cfg_pinmask_parse(value, &suc); - } - else if (streq(key, "g2_ch")) { - priv->cfg.group_channels[1] = (uint8_t) cfg_pinmask_parse(value, &suc); - } - else if (streq(key, "g3_ch")) { - priv->cfg.group_channels[2] = (uint8_t) cfg_pinmask_parse(value, &suc); - } - else if (streq(key, "g4_ch")) { - priv->cfg.group_channels[3] = (uint8_t) cfg_pinmask_parse(value, &suc); - } - else if (streq(key, "g5_ch")) { - priv->cfg.group_channels[4] = (uint8_t) cfg_pinmask_parse(value, &suc); - } - else if (streq(key, "g6_ch")) { - priv->cfg.group_channels[5] = (uint8_t) cfg_pinmask_parse(value, &suc); - } -#if HAVE_CH7 - else if (streq(key, "g7_ch")) { - priv->cfg.group_channels[6] = (uint8_t) cfg_pinmask_parse(value, &suc); - } -#endif -#if HAVE_CH8 - else if (streq(key, "g8_ch")) { - priv->cfg.group_channels[7] = (uint8_t) cfg_pinmask_parse(value, &suc); - } -#endif - else { + volatile char namebuf[10]; // must be volatile or gcc optimizes out the second compare and fucks it up + + for (int i = 0; i < 6; i++) { // skip 7,8 + SPRINTF(namebuf, "g%d_cap", i+1); + if (streq(key, namebuf)) { + priv->cfg.group_scaps[i] = (uint8_t) cfg_pinmask_parse(value, &suc); + goto matched; + } + + SPRINTF(namebuf, "g%d_ch", i+1); + if (streq(key, namebuf)) { + priv->cfg.group_channels[i] = (uint8_t) cfg_pinmask_parse(value, &suc); + goto matched; + } + } + return E_BAD_KEY; } +matched: if (!suc) return E_BAD_VALUE; return E_SUCCESS; } @@ -167,39 +143,13 @@ void UTOUCH_writeIni(Unit *unit, IniWriter *iw) iw_comment(iw, "Channels are numbered 1,2,3,4"); iw_cmt_newline(iw); - iw_comment(iw, "Group 1: A0,A1,A2,A3"); - iw_entry(iw, "g1_cap", cfg_pinmask_encode(priv->cfg.group_scaps[0], unit_tmp512, true)); - iw_entry(iw, "g1_ch", cfg_pinmask_encode(priv->cfg.group_channels[0], unit_tmp512, true)); - - iw_comment(iw, "Group 2: A4,A5,A6,A7"); - iw_entry(iw, "g2_cap", cfg_pinmask_encode(priv->cfg.group_scaps[1], unit_tmp512, true)); - iw_entry(iw, "g2_ch", cfg_pinmask_encode(priv->cfg.group_channels[1], unit_tmp512, true)); - - iw_comment(iw, "Group 3: C5,B0,B1,B2"); - iw_entry(iw, "g3_cap", cfg_pinmask_encode(priv->cfg.group_scaps[2], unit_tmp512, true)); - iw_entry(iw, "g3_ch", cfg_pinmask_encode(priv->cfg.group_channels[2], unit_tmp512, true)); - - iw_comment(iw, "Group 4: A9,A10,A11,A12"); - iw_entry(iw, "g4_cap", cfg_pinmask_encode(priv->cfg.group_scaps[3], unit_tmp512, true)); - iw_entry(iw, "g4_ch", cfg_pinmask_encode(priv->cfg.group_channels[3], unit_tmp512, true)); - - iw_comment(iw, "Group 5: B3,B4,B6,B7"); - iw_entry(iw, "g5_cap", cfg_pinmask_encode(priv->cfg.group_scaps[4], unit_tmp512, true)); - iw_entry(iw, "g5_ch", cfg_pinmask_encode(priv->cfg.group_channels[4], unit_tmp512, true)); - - iw_comment(iw, "Group 6: B11,B12,B13,B14"); - iw_entry(iw, "g6_cap", cfg_pinmask_encode(priv->cfg.group_scaps[5], unit_tmp512, true)); - iw_entry(iw, "g6_ch", cfg_pinmask_encode(priv->cfg.group_channels[5], unit_tmp512, true)); - -#if HAVE_CH7 - iw_comment(iw, "E2,E3,E4,E5"); - iw_entry(iw, "g7_cap", cfg_pinmask_encode(priv->cfg.group_scaps[6], unit_tmp512, true)); - iw_entry(iw, "g7_ch", cfg_pinmask_encode(priv->cfg.group_channels[6], unit_tmp512, true)); -#endif -#if HAVE_CH8 - iw_comment(iw, "D12,D13,D14,D15"); - iw_entry(iw, "g8_cap", cfg_pinmask_encode(priv->cfg.group_scaps[7], unit_tmp512, true)); - iw_entry(iw, "g8_ch", cfg_pinmask_encode(priv->cfg.group_channels[7], unit_tmp512, true)); -#endif + char namebuf[10]; + for (int i = 0; i < 6; i++) { // skip 7,8 + iw_commentf(iw, "Group%d - %s", i+1, utouch_group_labels[i]); + SPRINTF(namebuf, "g%d_cap", i+1); + iw_entry(iw, namebuf, cfg_pinmask_encode(priv->cfg.group_scaps[i], unit_tmp512, true)); + SPRINTF(namebuf, "g%d_ch", i+1); + iw_entry(iw, namebuf, cfg_pinmask_encode(priv->cfg.group_channels[i], unit_tmp512, true)); + } } diff --git a/units/touch/unit_touch.c b/units/touch/unit_touch.c index 59cd19c..0634244 100644 --- a/units/touch/unit_touch.c +++ b/units/touch/unit_touch.c @@ -11,7 +11,7 @@ // ------------------------------------------------------------------------ enum TouchCmd_ { - // + DUMMY=0 }; /** Handle a request message */ From 101d2534f40d4068db128bf68798293907945d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 25 Feb 2018 13:40:47 +0100 Subject: [PATCH 3/5] tsc disable debug --- units/touch/_touch_init.c | 14 +++++++------- units/touch/_touch_internal.h | 8 ++++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/units/touch/_touch_init.c b/units/touch/_touch_init.c index af00611..51ee6f0 100644 --- a/units/touch/_touch_init.c +++ b/units/touch/_touch_init.c @@ -44,7 +44,7 @@ error_t UTOUCH_init(Unit *unit) if (cap == 0) { if (ch != 0) { - dbg("TSC group %d has no cap!", (int)(gi+1)); + dbg_touch("TSC group %d has no cap!", (int)(gi+1)); return E_BAD_CONFIG; } continue; @@ -53,12 +53,12 @@ error_t UTOUCH_init(Unit *unit) if (ch == 0) continue; // if no channels, don't bother setting up anything if (cap != 2 && cap != 4 && cap != 8 && cap != 16) { - dbg("TSC group %d has more than 1 cap!", (int)(gi+1)); + dbg_touch("TSC group %d has more than 1 cap!", (int)(gi+1)); return E_BAD_CONFIG; } if (cap & ch) { - dbg("TSC pin can't be both channel and cap! (gpr %d)", (int)(gi+1)); + dbg_touch("TSC pin can't be both channel and cap! (gpr %d)", (int)(gi+1)); return E_BAD_CONFIG; } @@ -74,8 +74,8 @@ error_t UTOUCH_init(Unit *unit) // 7 and 8 (1-based) use AF1, else AF3 TRY(hw_configure_gpiorsc_af(r, gi >= 6 ? LL_GPIO_AF_1 : LL_GPIO_AF_3)); - if (iscap) dbg("TSC *cap @ %s", rsc_get_name(r)); - else dbg("TSC -ch @ %s", rsc_get_name(r)); + if (iscap) dbg_touch("TSC *cap @ %s", rsc_get_name(r)); + else dbg_touch("TSC -ch @ %s", rsc_get_name(r)); } // Sampling cap @@ -93,9 +93,9 @@ error_t UTOUCH_init(Unit *unit) } } - dbg("TSC phases:"); + dbg_touch("TSC phases:"); for (int i = 0; i < 3; i++) { - dbg(" %d: ch %08"PRIx32", g %02"PRIx32, i+1, priv->channels_phase[i], (uint32_t)priv->pgen_phase[i]); + dbg_touch(" %d: ch %08"PRIx32", g %02"PRIx32, i+1, priv->channels_phase[i], (uint32_t)priv->pgen_phase[i]); } return E_SUCCESS; diff --git a/units/touch/_touch_internal.h b/units/touch/_touch_internal.h index 9ce0e40..0a1bbca 100644 --- a/units/touch/_touch_internal.h +++ b/units/touch/_touch_internal.h @@ -11,6 +11,14 @@ #include "unit_base.h" +#define TSC_DEBUG 0 + +#if TSC_DEBUG +#define dbg_touch(...) dbg(...) +#else +#define dbg_touch(...) do{}while(0) +#endif + /** Private data structure */ struct priv { // settings From 41ad18cc7c3be0ec403d98e0573293ad063a8eff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 25 Feb 2018 22:47:40 +0100 Subject: [PATCH 4/5] improvements + added a toggle for interlaced, not yet fully implemented --- gex.mk | 2 +- platform/irq_dispatcher.c | 11 ++- units/touch/_touch_core.c | 111 ++++++++++++++++++++++++++++++ units/touch/_touch_init.c | 125 +++++++++++++++++++++++++++------- units/touch/_touch_internal.h | 24 +++++-- units/touch/_touch_settings.c | 22 ++++-- units/touch/unit_touch.c | 29 ++++---- 7 files changed, 277 insertions(+), 47 deletions(-) create mode 100644 units/touch/_touch_core.c diff --git a/gex.mk b/gex.mk index 2066ea0..46d79b7 100644 --- a/gex.mk +++ b/gex.mk @@ -96,7 +96,7 @@ GEX_CDEFS = $(GEX_CDEFS_BASE) \ -DUSE_STACK_MONITOR=1 \ -DUSE_DEBUG_UART=1 \ -DDEBUG_MALLOC=0 \ - -DDEBUG_RSC=1 + -DDEBUG_RSC=0 endif diff --git a/platform/irq_dispatcher.c b/platform/irq_dispatcher.c index 93ff1cf..01c357f 100644 --- a/platform/irq_dispatcher.c +++ b/platform/irq_dispatcher.c @@ -69,6 +69,7 @@ static struct callbacks_ { struct cbslot tim16; struct cbslot adc1; + struct cbslot tsc; // XXX add more callbacks here when needed } callbacks; @@ -92,7 +93,8 @@ void irqd_init(void) HAL_NVIC_SetPriority(EXTI2_3_IRQn, 2, 0); HAL_NVIC_SetPriority(EXTI4_15_IRQn, 2, 0); -// NVIC_EnableIRQ(TSC_IRQn); /*!< Touch Sensing Controller Interrupts */ + NVIC_EnableIRQ(TSC_IRQn); /*!< Touch Sensing Controller Interrupts */ + HAL_NVIC_SetPriority(TSC_IRQn, 2, 0); NVIC_EnableIRQ(DMA1_Channel1_IRQn); /*!< DMA1 Channel 1 Interrupt */ NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); /*!< DMA1 Channel 2 and Channel 3 Interrupt */ @@ -178,6 +180,8 @@ static struct cbslot *get_slot_for_periph(void *periph) else if (periph == TIM16) slot = &callbacks.tim16; // 17 - used by timebase + else if (periph == TSC) slot = &callbacks.tsc; + else if (periph == ADC1) slot = &callbacks.adc1; else if (periph >= EXTIS[0] && periph <= EXTIS[15]) { @@ -352,6 +356,11 @@ void ADC1_COMP_IRQHandler(void) CALL_IRQ_HANDLER(callbacks.adc1); } +void TSC_IRQHandler(void) +{ + CALL_IRQ_HANDLER(callbacks.tsc); +} + // other ISRs... diff --git a/units/touch/_touch_core.c b/units/touch/_touch_core.c new file mode 100644 index 0000000..8c1cf7b --- /dev/null +++ b/units/touch/_touch_core.c @@ -0,0 +1,111 @@ +// +// Created by MightyPork on 2018/02/25. +// + +#include "platform.h" +#include "unit_base.h" +#include "unit_touch.h" + +#define TOUCH_INTERNAL + +#include "_touch_internal.h" + +#define DIS_TIME 1 + +static void startNextPhase(struct priv *priv); + +void UTOUCH_HandleIrq(void *arg) +{ + Unit *unit = arg; + struct priv *priv = unit->data; + + if (TSC->ISR & TSC_ISR_MCEF) { + priv->status = UTSC_STATUS_FAIL; + dbg_touch("TSC Failure."); + TSC->ICR = TSC_ICR_EOAIC | TSC_ICR_MCEIC; + } + + if (TSC->ISR & TSC_ISR_EOAF) { + TSC->ICR = TSC_ICR_EOAIC; +// assert_param((TSC->IOGCSR>>16) == priv->groups_phase[priv->next_phase]); + + // Store captured data + const uint32_t chmask = priv->channels_phase[priv->next_phase]; + for (int i = 0; i < 32; i++) { + if (chmask & (1<readouts[i] = (uint16_t) (TSC->IOGXCR[i >> 2] & 0x3FFF); + } + } + + priv->next_phase++; + // check if we've run out of existing or populated groups + if (priv->next_phase == 3 || priv->groups_phase[priv->next_phase] == 0) { + priv->next_phase = 0; + priv->status = UTSC_STATUS_READY; + // we'll stay in READY after the first loop until an error occurs or it's re-inited + } + + TSC->CR &= ~TSC_CR_IODEF; // pull low - discharge + } + + priv->ongoing = false; + priv->discharge_delay = DIS_TIME; +} + +#if TSC_DEBUG +static volatile uint32_t xcnt=0; +#endif + +void UTOUCH_updateTick(Unit *unit) +{ +#if TSC_DEBUG + xcnt++; +#endif + + struct priv *priv = unit->data; + + if (priv->ongoing) { + return; + } + + if (priv->discharge_delay > 0) { + priv->discharge_delay--; + } else { + startNextPhase(priv); + } + +#if TSC_DEBUG + if(xcnt >= 250) { + xcnt=0; + PRINTF("> "); + for (int i = 0; i < 32; i++) { + if (priv->all_channels_mask & (1<readouts[i]); + } + } + PRINTF("\r\n"); + } +#endif +} + +static void startNextPhase(struct priv *priv) +{ + if (priv->next_phase == 0 && priv->groups_phase[0] == 0) { + // no groups are configured + return; + } + + TSC->IOGCSR = priv->groups_phase[priv->next_phase]; + TSC->IOCCR = priv->channels_phase[priv->next_phase]; + TSC->ICR = TSC_ICR_EOAIC | TSC_ICR_MCEIC; + + if (priv->cfg.interlaced) { + TSC->CR |= TSC_CR_IODEF; + // floaty (must be used for interlaced pads) + // note: interlaced pads also need to be sampled individually + } + + // Go! + priv->ongoing = true; + TSC->CR |= TSC_CR_START; +} diff --git a/units/touch/_touch_init.c b/units/touch/_touch_init.c index 51ee6f0..965d227 100644 --- a/units/touch/_touch_init.c +++ b/units/touch/_touch_init.c @@ -2,11 +2,11 @@ // Created by MightyPork on 2018/02/03. // -#include #include "platform.h" #include "unit_base.h" #define TOUCH_INTERNAL + #include "_touch_internal.h" /** Allocate data structure and set defaults */ @@ -33,10 +33,47 @@ error_t UTOUCH_init(Unit *unit) bool suc = true; struct priv *priv = unit->data; + unit->tick_interval = 1; // sample every 1 ms + TRY(rsc_claim(unit, R_TSC)); + // simple bound checks, just clamp without error + if (priv->cfg.charge_time > 16) priv->cfg.charge_time = 16; + if (priv->cfg.charge_time < 1) priv->cfg.charge_time = 1; + + if (priv->cfg.drain_time > 16) priv->cfg.drain_time = 16; + if (priv->cfg.drain_time < 1) priv->cfg.drain_time = 1; + + if (priv->cfg.spread_deviation > 128) priv->cfg.drain_time = 128; + + if (priv->cfg.ss_presc > 2) priv->cfg.ss_presc = 2; + if (priv->cfg.ss_presc < 1) priv->cfg.ss_presc = 1; + + if (priv->cfg.sense_timeout > 7) priv->cfg.sense_timeout = 7; + if (priv->cfg.sense_timeout < 1) priv->cfg.sense_timeout = 1; + + uint8_t tmppgpresc = priv->cfg.pg_presc; + if (tmppgpresc == 0) return E_BAD_CONFIG; + uint8_t pgpresc_reg = 0; + while ((tmppgpresc & 1) == 0 && tmppgpresc != 0) { + pgpresc_reg++; + tmppgpresc >>= 1; + } + if (tmppgpresc != 1 || pgpresc_reg > 7) { + dbg("Bad pgpresc"); + return E_BAD_CONFIG; // TODO better reporting + } + + if ((pgpresc_reg==0 && priv->cfg.drain_time<=2) || (pgpresc_reg==1 && priv->cfg.drain_time==0)) { + dbg("Illegal PGPSC vs CTPL"); + return E_BAD_CONFIG; + } + // enable clock hw_periph_clock_enable(TSC); + // reset + __HAL_RCC_TSC_FORCE_RESET(); + __HAL_RCC_TSC_RELEASE_RESET(); for (int gi = 0; gi < 8; gi++) { const uint8_t cap = priv->cfg.group_scaps[gi]; @@ -44,7 +81,7 @@ error_t UTOUCH_init(Unit *unit) if (cap == 0) { if (ch != 0) { - dbg_touch("TSC group %d has no cap!", (int)(gi+1)); + dbg_touch("TSC group %d has no cap!", (int) (gi + 1)); return E_BAD_CONFIG; } continue; @@ -53,51 +90,89 @@ error_t UTOUCH_init(Unit *unit) if (ch == 0) continue; // if no channels, don't bother setting up anything if (cap != 2 && cap != 4 && cap != 8 && cap != 16) { - dbg_touch("TSC group %d has more than 1 cap!", (int)(gi+1)); + dbg_touch("TSC group %d has more than 1 cap!", (int) (gi + 1)); return E_BAD_CONFIG; } if (cap & ch) { - dbg_touch("TSC pin can't be both channel and cap! (gpr %d)", (int)(gi+1)); + dbg_touch("TSC pin can't be both channel and cap! (gpr %d)", (int) (gi + 1)); return E_BAD_CONFIG; } - int chnum = 0; + // This is a loop through the pins in a group gi + int phasenum = 0; for (int pi = 0; pi < 4; pi++) { // pin numbers are 1-based in the config const bool iscap = 0 != (cap & (2 << pi)); const bool isch = 0 != (ch & (2 << pi)); - if (iscap || isch) { - Resource r = utouch_group_rscs[gi][pi]; - TRY(rsc_claim(unit, r)); - // 7 and 8 (1-based) use AF1, else AF3 - TRY(hw_configure_gpiorsc_af(r, gi >= 6 ? LL_GPIO_AF_1 : LL_GPIO_AF_3)); + if (!iscap && !isch) continue; - if (iscap) dbg_touch("TSC *cap @ %s", rsc_get_name(r)); - else dbg_touch("TSC -ch @ %s", rsc_get_name(r)); - } + Resource r = utouch_group_rscs[gi][pi]; + TRY(rsc_claim(unit, r)); + + GPIO_TypeDef *port; + uint32_t ll; + assert_param(hw_pinrsc2ll(r, &port, &ll)); + LL_GPIO_SetPinOutputType(port, ll, isch ? LL_GPIO_OUTPUT_PUSHPULL : LL_GPIO_OUTPUT_OPENDRAIN); + + // 7 and 8 (1-based) use AF1, else AF3 + TRY(hw_configure_gpiorsc_af(r, gi >= 6 ? LL_GPIO_AF_1 : LL_GPIO_AF_3)); + + uint32_t bit = (uint32_t) (1 << (gi * 4 + pi)); - // Sampling cap if (iscap) { - TSC->IOSCR |= (cap>>1) << (gi*4); - } + dbg_touch("TSC cap @ %s", rsc_get_name(r)); + // Sampling cap + TSC->IOSCR |= bit; - // channels are configured individually when read. - // we prepare bitmaps to use for the read groups (all can be read in at most 3 steps) - if (isch) { - priv->channels_phase[chnum] |= 1 << (gi*4+pi); - priv->pgen_phase[chnum] |= 1 << gi; - chnum++; + // Disable pin hysteresis (causes noise) + TSC->IOHCR ^= bit; + } + else { + dbg_touch("TSC ch @ %s", rsc_get_name(r)); + + // channels are configured individually when read. + // we prepare bitmaps to use for the read groups (all can be read in at most 3 steps) + priv->channels_phase[phasenum] |= bit; // this is used for the channel selection register + priv->groups_phase[phasenum] |= 1 << gi; // this will be used for the group enable register, if all 0, this and any following phases are unused. + phasenum++; } } } + // common TSC config + TSC->CR = + ((priv->cfg.charge_time - 1) << TSC_CR_CTPH_Pos) | + ((priv->cfg.drain_time - 1) << TSC_CR_CTPL_Pos) | + ((priv->cfg.ss_presc - 1) << TSC_CR_SSPSC_Pos) | + (pgpresc_reg << TSC_CR_PGPSC_Pos) | + ((priv->cfg.sense_timeout - 1) << TSC_CR_MCV_Pos) | + TSC_CR_TSCE; + + if (priv->cfg.spread_deviation > 0) { + TSC->CR |= ((priv->cfg.spread_deviation - 1) << TSC_CR_SSD_Pos) | TSC_CR_SSE; + } + + dbg_touch("CR = %08x, ht is %d, lt is %d", TSC->CR, priv->cfg.charge_time, priv->cfg.drain_time); + + // iofloat is used for discharging + + // Enable the interrupts + TSC->IER = TSC_IER_EOAIE | TSC_IER_MCEIE; + irqd_attach(TSC, UTOUCH_HandleIrq, unit); + dbg_touch("TSC phases:"); + priv->all_channels_mask = 0; for (int i = 0; i < 3; i++) { - dbg_touch(" %d: ch %08"PRIx32", g %02"PRIx32, i+1, priv->channels_phase[i], (uint32_t)priv->pgen_phase[i]); + priv->all_channels_mask |= priv->channels_phase[i]; + dbg_touch(" %d: ch %08"PRIx32", g %02"PRIx32, i + 1, priv->channels_phase[i], (uint32_t) priv->groups_phase[i]); } + priv->status = UTSC_STATUS_BUSY; // first loop ... + priv->next_phase = 0; + UTOUCH_updateTick(unit); + return E_SUCCESS; } @@ -108,11 +183,13 @@ void UTOUCH_deInit(Unit *unit) struct priv *priv = unit->data; // de-init peripherals - if (unit->status == E_SUCCESS ) { + if (unit->status == E_SUCCESS) { hw_periph_clock_disable(TSC); // clear all registers to their default values __HAL_RCC_TSC_FORCE_RESET(); __HAL_RCC_TSC_RELEASE_RESET(); + + irqd_detach(TSC, UTOUCH_HandleIrq); } // Release all resources, deinit pins diff --git a/units/touch/_touch_internal.h b/units/touch/_touch_internal.h index 0a1bbca..056fe11 100644 --- a/units/touch/_touch_internal.h +++ b/units/touch/_touch_internal.h @@ -11,14 +11,20 @@ #include "unit_base.h" -#define TSC_DEBUG 0 +#define TSC_DEBUG 1 #if TSC_DEBUG -#define dbg_touch(...) dbg(...) +#define dbg_touch(f,...) dbg(f,##__VA_ARGS__) #else -#define dbg_touch(...) do{}while(0) +#define dbg_touch(f,...) do{}while(0) #endif +enum utsc_status { + UTSC_STATUS_BUSY = 0, + UTSC_STATUS_READY = 1, + UTSC_STATUS_FAIL = 2 +}; + /** Private data structure */ struct priv { // settings @@ -32,12 +38,18 @@ struct priv { // the schmitts must be disabled on all used channels, restored to 0xFFFF on deinit uint8_t group_scaps[8]; uint8_t group_channels[8]; + bool interlaced; } cfg; uint8_t next_phase; + uint8_t discharge_delay; uint32_t channels_phase[3]; - uint8_t pgen_phase[3]; + uint8_t groups_phase[3]; uint16_t readouts[32]; + uint32_t all_channels_mask; + bool ongoing; + + enum utsc_status status; }; extern const char *utouch_group_labels[8]; @@ -68,4 +80,8 @@ error_t UTOUCH_init(Unit *unit); /** Tear down the unit */ void UTOUCH_deInit(Unit *unit); +void UTOUCH_updateTick(Unit *unit); + +void UTOUCH_HandleIrq(void *arg); + #endif //GEX_F072_TOUCH_INTERNAL_H diff --git a/units/touch/_touch_settings.c b/units/touch/_touch_settings.c index def2f96..3340c06 100644 --- a/units/touch/_touch_settings.c +++ b/units/touch/_touch_settings.c @@ -46,6 +46,10 @@ void UTOUCH_loadBinary(Unit *unit, PayloadParser *pp) priv->cfg.sense_timeout = pp_u8(pp); pp_buf(pp, priv->cfg.group_scaps, 8); pp_buf(pp, priv->cfg.group_channels, 8); + + if (version >= 1) { + priv->cfg.interlaced = pp_bool(pp); + } } /** Write to a binary buffer for storing in Flash */ @@ -53,7 +57,7 @@ void UTOUCH_writeBinary(Unit *unit, PayloadBuilder *pb) { struct priv *priv = unit->data; - pb_u8(pb, 0); // version + pb_u8(pb, 1); // version pb_u8(pb, priv->cfg.charge_time); pb_u8(pb, priv->cfg.drain_time); @@ -63,6 +67,7 @@ void UTOUCH_writeBinary(Unit *unit, PayloadBuilder *pb) pb_u8(pb, priv->cfg.sense_timeout); pb_buf(pb, priv->cfg.group_scaps, 8); pb_buf(pb, priv->cfg.group_channels, 8); + pb_bool(pb, priv->cfg.interlaced); } // ------------------------------------------------------------------------ @@ -91,6 +96,9 @@ error_t UTOUCH_loadIni(Unit *unit, const char *key, const char *value) else if (streq(key, "sense-timeout")) { priv->cfg.sense_timeout = cfg_u8_parse(value, &suc); } + else if (streq(key, "interlaced-pads")) { + priv->cfg.interlaced = cfg_bool_parse(value, &suc); + } else { volatile char namebuf[10]; // must be volatile or gcc optimizes out the second compare and fucks it up @@ -126,17 +134,23 @@ void UTOUCH_writeIni(Unit *unit, IniWriter *iw) iw_cmt_newline(iw); iw_comment(iw, "Pulse generator clock prescaller (1,2,4,...,128)"); - iw_entry(iw, "pg-clock-prediv", "%d", (int)priv->cfg.ss_presc); + iw_entry(iw, "pg-clock-prediv", "%d", (int)priv->cfg.pg_presc); iw_comment(iw, "Sense pad charging time (1-16)"); iw_entry(iw, "charge-time", "%d", (int)priv->cfg.charge_time); iw_comment(iw, "Charge transfer time (1-16)"); iw_entry(iw, "drain-time", "%d", (int)priv->cfg.drain_time); + iw_comment(iw, "Measurement timeout (1-7)"); + iw_entry(iw, "sense-timeout", "%d", (int)priv->cfg.sense_timeout); + + iw_cmt_newline(iw); iw_comment(iw, "Spread spectrum max deviation (0-128,0=off)"); iw_entry(iw, "ss-deviation", "%d", (int)priv->cfg.spread_deviation); iw_comment(iw, "Spreading clock prescaller (1,2)"); iw_entry(iw, "ss-clock-prediv", "%d", (int)priv->cfg.ss_presc); - iw_comment(iw, "Measurement timeout (1-7)"); - iw_entry(iw, "sense-timeout", "%d", (int)priv->cfg.sense_timeout); + + iw_cmt_newline(iw); + iw_comment(iw, "Optimize for interlaced pads"); + iw_entry(iw, "interlaced-pads", str_yn(priv->cfg.interlaced)); iw_cmt_newline(iw); iw_comment(iw, "Each used group must have 1 sampling capacitor and 1-3 channels."); diff --git a/units/touch/unit_touch.c b/units/touch/unit_touch.c index 0634244..dd42aee 100644 --- a/units/touch/unit_touch.c +++ b/units/touch/unit_touch.c @@ -11,13 +11,28 @@ // ------------------------------------------------------------------------ enum TouchCmd_ { - DUMMY=0 + CMD_READ=0 }; /** Handle a request message */ static error_t UTOUCH_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp) { + struct priv* priv = unit->data; + switch (command) { + case CMD_READ: + if (priv->status == UTSC_STATUS_BUSY) return E_BUSY; + if (priv->status == UTSC_STATUS_FAIL) return E_HW_TIMEOUT; + + PayloadBuilder pb = pb_start(unit_tmp512, UNIT_TMP_LEN, NULL); + for (int i = 0; i < 32; i++) { + if (priv->all_channels_mask & (1<readouts[i]); + } + } + com_respond_pb(frame_id, MSG_SUCCESS, &pb); + return E_SUCCESS; + default: return E_UNKNOWN_COMMAND; } @@ -25,18 +40,6 @@ static error_t UTOUCH_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, // ------------------------------------------------------------------------ -/** - * Handle update-tick (if configured in init) - * - * @param unit - */ -static void UTOUCH_updateTick(Unit *unit) -{ - // -} - -// ------------------------------------------------------------------------ - /** Unit template */ const UnitDriver UNIT_TOUCH = { .name = "TOUCH", From 5019bf225dfee36fd9c01d6a3396aa5d4f28794b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Mon, 26 Feb 2018 09:02:41 +0100 Subject: [PATCH 5/5] touch interleaved sense mode, improved blinking in file writes via the api --- comm/messages.c | 5 ++++ platform/status_led.c | 16 ++++++++++++- platform/status_led.h | 1 + units/touch/_touch_core.c | 45 ++++++++++++++++++++++------------- units/touch/_touch_init.c | 39 ++++++++++++++++++++---------- units/touch/_touch_internal.h | 2 +- units/touch/_touch_settings.c | 2 +- 7 files changed, 79 insertions(+), 31 deletions(-) diff --git a/comm/messages.c b/comm/messages.c index 2b4105b..620a17e 100644 --- a/comm/messages.c +++ b/comm/messages.c @@ -2,6 +2,7 @@ // Created by MightyPork on 2017/11/21. // +#include #include "platform.h" #include "framework/settings.h" #include "utils/ini_parser.h" @@ -91,6 +92,7 @@ static TF_Result lst_ini_export(TinyFrame *tf, TF_Msg *msg) bulk->userdata = NULL; bulkread_start(tf, bulk); + Indicator_Effect(STATUS_DISK_BUSY_SHORT); return TF_STAY; } @@ -152,6 +154,8 @@ static TF_Result lst_ini_import(TinyFrame *tf, TF_Msg *msg) bulkwrite_start(tf, bulk); + Indicator_Effect(STATUS_DISK_BUSY); + done: return TF_STAY; } @@ -161,6 +165,7 @@ done: /** Listener: Save settings to Flash */ static TF_Result lst_persist_cfg(TinyFrame *tf, TF_Msg *msg) { + Indicator_Effect(STATUS_DISK_REMOVED); settings_save(); return TF_STAY; } diff --git a/platform/status_led.c b/platform/status_led.c index cc66f2f..e031965 100644 --- a/platform/status_led.c +++ b/platform/status_led.c @@ -61,6 +61,12 @@ void Indicator_Effect(enum GEX_StatusIndicator indicator) led_on(); } + // prevent the two disk ops interfering (happens in write-reload) + if (indicator == STATUS_DISK_BUSY && active_effect == STATUS_DISK_BUSY_SHORT) return; + if (indicator == STATUS_DISK_BUSY_SHORT && active_effect == STATUS_DISK_BUSY) return; + + // TODO add some better protection against effect overlap? + active_effect = indicator; effect_time = 0; } @@ -119,7 +125,15 @@ void Indicator_Tick(void) active_effect = STATUS_NONE; } else if (effect_time % 100 == 0) led_on(); - else if (effect_time % 100 == 50) led_off(); + else if (effect_time % 100 == 20) led_off(); + } + else if (active_effect == STATUS_DISK_BUSY_SHORT) { + if (effect_time >= 200) { + led_off(); + active_effect = STATUS_NONE; + } + else if (effect_time % 100 == 0) led_on(); + else if (effect_time % 100 == 20) led_off(); } else if (active_effect == STATUS_WELCOME) { if (effect_time == 0) led_on(); diff --git a/platform/status_led.h b/platform/status_led.h index f61e3a9..5dbeb2d 100644 --- a/platform/status_led.h +++ b/platform/status_led.h @@ -16,6 +16,7 @@ enum GEX_StatusIndicator { STATUS_NONE = 0, STATUS_FAULT, STATUS_DISK_BUSY, + STATUS_DISK_BUSY_SHORT, STATUS_DISK_ATTACHED, STATUS_DISK_REMOVED, STATUS_WELCOME, diff --git a/units/touch/_touch_core.c b/units/touch/_touch_core.c index 8c1cf7b..76f8ebb 100644 --- a/units/touch/_touch_core.c +++ b/units/touch/_touch_core.c @@ -30,7 +30,7 @@ void UTOUCH_HandleIrq(void *arg) // assert_param((TSC->IOGCSR>>16) == priv->groups_phase[priv->next_phase]); // Store captured data - const uint32_t chmask = priv->channels_phase[priv->next_phase]; + const uint32_t chmask = TSC->IOCCR; for (int i = 0; i < 32; i++) { if (chmask & (1<readouts[i] = (uint16_t) (TSC->IOGXCR[i >> 2] & 0x3FFF); @@ -38,11 +38,14 @@ void UTOUCH_HandleIrq(void *arg) } priv->next_phase++; - // check if we've run out of existing or populated groups - if (priv->next_phase == 3 || priv->groups_phase[priv->next_phase] == 0) { - priv->next_phase = 0; - priv->status = UTSC_STATUS_READY; - // we'll stay in READY after the first loop until an error occurs or it's re-inited + + if (!priv->cfg.interlaced) { + // check if we've run out of existing or populated groups + if (priv->next_phase == 3 || priv->groups_phase[priv->next_phase] == 0) { + priv->next_phase = 0; + priv->status = UTSC_STATUS_READY; + // we'll stay in READY after the first loop until an error occurs or it's re-inited + } } TSC->CR &= ~TSC_CR_IODEF; // pull low - discharge @@ -90,21 +93,31 @@ void UTOUCH_updateTick(Unit *unit) static void startNextPhase(struct priv *priv) { - if (priv->next_phase == 0 && priv->groups_phase[0] == 0) { - // no groups are configured - return; - } - - TSC->IOGCSR = priv->groups_phase[priv->next_phase]; - TSC->IOCCR = priv->channels_phase[priv->next_phase]; - TSC->ICR = TSC_ICR_EOAIC | TSC_ICR_MCEIC; + if (priv->all_channels_mask == 0) return; if (priv->cfg.interlaced) { + // Find the next non-zero bit, wrap around if needed + while ((priv->all_channels_mask & (1<next_phase))==0) { + priv->next_phase++; + if (priv->next_phase == 32) { + priv->next_phase = 0; + priv->status = UTSC_STATUS_READY; + } + } + TSC->IOGCSR = (uint32_t) (1 << (priv->next_phase >> 2)); // phase divided by 4 + TSC->IOCCR = (uint32_t) (1 << priv->next_phase); + + // interlaced - float neighbouring electrodes TSC->CR |= TSC_CR_IODEF; - // floaty (must be used for interlaced pads) - // note: interlaced pads also need to be sampled individually + } else { + TSC->IOGCSR = priv->groups_phase[priv->next_phase]; + TSC->IOCCR = priv->channels_phase[priv->next_phase]; + + // separate - keep neighbouring electrodes at GND } + TSC->ICR = TSC_ICR_EOAIC | TSC_ICR_MCEIC; + // Go! priv->ongoing = true; TSC->CR |= TSC_CR_START; diff --git a/units/touch/_touch_init.c b/units/touch/_touch_init.c index 965d227..4321b4f 100644 --- a/units/touch/_touch_init.c +++ b/units/touch/_touch_init.c @@ -75,6 +75,8 @@ error_t UTOUCH_init(Unit *unit) __HAL_RCC_TSC_FORCE_RESET(); __HAL_RCC_TSC_RELEASE_RESET(); + priv->all_channels_mask = 0; + for (int gi = 0; gi < 8; gi++) { const uint8_t cap = priv->cfg.group_scaps[gi]; const uint8_t ch = priv->cfg.group_channels[gi]; @@ -132,11 +134,16 @@ error_t UTOUCH_init(Unit *unit) else { dbg_touch("TSC ch @ %s", rsc_get_name(r)); - // channels are configured individually when read. - // we prepare bitmaps to use for the read groups (all can be read in at most 3 steps) - priv->channels_phase[phasenum] |= bit; // this is used for the channel selection register - priv->groups_phase[phasenum] |= 1 << gi; // this will be used for the group enable register, if all 0, this and any following phases are unused. - phasenum++; + if (priv->cfg.interlaced) { + // interlaced - only update the mask beforehand + priv->all_channels_mask |= bit; + } else { + // channels are configured individually when read. + // we prepare bitmaps to use for the read groups (all can be read in at most 3 steps) + priv->channels_phase[phasenum] |= bit; // this is used for the channel selection register + priv->groups_phase[phasenum] |= 1 << gi; // this will be used for the group enable register, if all 0, this and any following phases are unused. + phasenum++; + } } } } @@ -154,7 +161,9 @@ error_t UTOUCH_init(Unit *unit) TSC->CR |= ((priv->cfg.spread_deviation - 1) << TSC_CR_SSD_Pos) | TSC_CR_SSE; } - dbg_touch("CR = %08x, ht is %d, lt is %d", TSC->CR, priv->cfg.charge_time, priv->cfg.drain_time); + dbg_touch("CR = %08x, ht is %d, lt is %d", (int)TSC->CR, + (int)priv->cfg.charge_time, + (int)priv->cfg.drain_time); // iofloat is used for discharging @@ -162,16 +171,22 @@ error_t UTOUCH_init(Unit *unit) TSC->IER = TSC_IER_EOAIE | TSC_IER_MCEIE; irqd_attach(TSC, UTOUCH_HandleIrq, unit); - dbg_touch("TSC phases:"); - priv->all_channels_mask = 0; - for (int i = 0; i < 3; i++) { - priv->all_channels_mask |= priv->channels_phase[i]; - dbg_touch(" %d: ch %08"PRIx32", g %02"PRIx32, i + 1, priv->channels_phase[i], (uint32_t) priv->groups_phase[i]); + if (!priv->cfg.interlaced) { + dbg_touch("TSC phases:"); + for (int i = 0; i < 3; i++) { + priv->all_channels_mask |= priv->channels_phase[i]; + + dbg_touch(" %d: ch %08"PRIx32", g %02"PRIx32, + i + 1, + priv->channels_phase[i], + (uint32_t) priv->groups_phase[i]); + } } priv->status = UTSC_STATUS_BUSY; // first loop ... priv->next_phase = 0; - UTOUCH_updateTick(unit); + + // starts in the tick callback return E_SUCCESS; } diff --git a/units/touch/_touch_internal.h b/units/touch/_touch_internal.h index 056fe11..ffc6d39 100644 --- a/units/touch/_touch_internal.h +++ b/units/touch/_touch_internal.h @@ -11,7 +11,7 @@ #include "unit_base.h" -#define TSC_DEBUG 1 +#define TSC_DEBUG 0 #if TSC_DEBUG #define dbg_touch(f,...) dbg(f,##__VA_ARGS__) diff --git a/units/touch/_touch_settings.c b/units/touch/_touch_settings.c index 3340c06..9c2b244 100644 --- a/units/touch/_touch_settings.c +++ b/units/touch/_touch_settings.c @@ -149,7 +149,7 @@ void UTOUCH_writeIni(Unit *unit, IniWriter *iw) iw_entry(iw, "ss-clock-prediv", "%d", (int)priv->cfg.ss_presc); iw_cmt_newline(iw); - iw_comment(iw, "Optimize for interlaced pads"); + iw_comment(iw, "Optimize for interlaced pads (individual sampling with others floating)"); iw_entry(iw, "interlaced-pads", str_yn(priv->cfg.interlaced)); iw_cmt_newline(iw);