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 */