touch interleaved sense mode, improved blinking in file writes via the api

remotes/github/bad-doublebuf
Ondřej Hruška 6 years ago
parent 41ad18cc7c
commit 5019bf225d
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 5
      comm/messages.c
  2. 16
      platform/status_led.c
  3. 1
      platform/status_led.h
  4. 31
      units/touch/_touch_core.c
  5. 23
      units/touch/_touch_init.c
  6. 2
      units/touch/_touch_internal.h
  7. 2
      units/touch/_touch_settings.c

@ -2,6 +2,7 @@
// Created by MightyPork on 2017/11/21. // Created by MightyPork on 2017/11/21.
// //
#include <platform/status_led.h>
#include "platform.h" #include "platform.h"
#include "framework/settings.h" #include "framework/settings.h"
#include "utils/ini_parser.h" #include "utils/ini_parser.h"
@ -91,6 +92,7 @@ static TF_Result lst_ini_export(TinyFrame *tf, TF_Msg *msg)
bulk->userdata = NULL; bulk->userdata = NULL;
bulkread_start(tf, bulk); bulkread_start(tf, bulk);
Indicator_Effect(STATUS_DISK_BUSY_SHORT);
return TF_STAY; return TF_STAY;
} }
@ -152,6 +154,8 @@ static TF_Result lst_ini_import(TinyFrame *tf, TF_Msg *msg)
bulkwrite_start(tf, bulk); bulkwrite_start(tf, bulk);
Indicator_Effect(STATUS_DISK_BUSY);
done: done:
return TF_STAY; return TF_STAY;
} }
@ -161,6 +165,7 @@ done:
/** Listener: Save settings to Flash */ /** Listener: Save settings to Flash */
static TF_Result lst_persist_cfg(TinyFrame *tf, TF_Msg *msg) static TF_Result lst_persist_cfg(TinyFrame *tf, TF_Msg *msg)
{ {
Indicator_Effect(STATUS_DISK_REMOVED);
settings_save(); settings_save();
return TF_STAY; return TF_STAY;
} }

@ -61,6 +61,12 @@ void Indicator_Effect(enum GEX_StatusIndicator indicator)
led_on(); 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; active_effect = indicator;
effect_time = 0; effect_time = 0;
} }
@ -119,7 +125,15 @@ void Indicator_Tick(void)
active_effect = STATUS_NONE; active_effect = STATUS_NONE;
} }
else if (effect_time % 100 == 0) led_on(); 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) { else if (active_effect == STATUS_WELCOME) {
if (effect_time == 0) led_on(); if (effect_time == 0) led_on();

@ -16,6 +16,7 @@ enum GEX_StatusIndicator {
STATUS_NONE = 0, STATUS_NONE = 0,
STATUS_FAULT, STATUS_FAULT,
STATUS_DISK_BUSY, STATUS_DISK_BUSY,
STATUS_DISK_BUSY_SHORT,
STATUS_DISK_ATTACHED, STATUS_DISK_ATTACHED,
STATUS_DISK_REMOVED, STATUS_DISK_REMOVED,
STATUS_WELCOME, STATUS_WELCOME,

@ -30,7 +30,7 @@ void UTOUCH_HandleIrq(void *arg)
// assert_param((TSC->IOGCSR>>16) == priv->groups_phase[priv->next_phase]); // assert_param((TSC->IOGCSR>>16) == priv->groups_phase[priv->next_phase]);
// Store captured data // 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++) { for (int i = 0; i < 32; i++) {
if (chmask & (1<<i)) { if (chmask & (1<<i)) {
priv->readouts[i] = (uint16_t) (TSC->IOGXCR[i >> 2] & 0x3FFF); priv->readouts[i] = (uint16_t) (TSC->IOGXCR[i >> 2] & 0x3FFF);
@ -38,12 +38,15 @@ void UTOUCH_HandleIrq(void *arg)
} }
priv->next_phase++; priv->next_phase++;
if (!priv->cfg.interlaced) {
// check if we've run out of existing or populated groups // check if we've run out of existing or populated groups
if (priv->next_phase == 3 || priv->groups_phase[priv->next_phase] == 0) { if (priv->next_phase == 3 || priv->groups_phase[priv->next_phase] == 0) {
priv->next_phase = 0; priv->next_phase = 0;
priv->status = UTSC_STATUS_READY; priv->status = UTSC_STATUS_READY;
// we'll stay in READY after the first loop until an error occurs or it's re-inited // 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 TSC->CR &= ~TSC_CR_IODEF; // pull low - discharge
} }
@ -90,21 +93,31 @@ void UTOUCH_updateTick(Unit *unit)
static void startNextPhase(struct priv *priv) static void startNextPhase(struct priv *priv)
{ {
if (priv->next_phase == 0 && priv->groups_phase[0] == 0) { if (priv->all_channels_mask == 0) return;
// no groups are configured
return; if (priv->cfg.interlaced) {
// Find the next non-zero bit, wrap around if needed
while ((priv->all_channels_mask & (1<<priv->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;
} else {
TSC->IOGCSR = priv->groups_phase[priv->next_phase]; TSC->IOGCSR = priv->groups_phase[priv->next_phase];
TSC->IOCCR = priv->channels_phase[priv->next_phase]; TSC->IOCCR = priv->channels_phase[priv->next_phase];
TSC->ICR = TSC_ICR_EOAIC | TSC_ICR_MCEIC;
if (priv->cfg.interlaced) { // separate - keep neighbouring electrodes at GND
TSC->CR |= TSC_CR_IODEF;
// floaty (must be used for interlaced pads)
// note: interlaced pads also need to be sampled individually
} }
TSC->ICR = TSC_ICR_EOAIC | TSC_ICR_MCEIC;
// Go! // Go!
priv->ongoing = true; priv->ongoing = true;
TSC->CR |= TSC_CR_START; TSC->CR |= TSC_CR_START;

@ -75,6 +75,8 @@ error_t UTOUCH_init(Unit *unit)
__HAL_RCC_TSC_FORCE_RESET(); __HAL_RCC_TSC_FORCE_RESET();
__HAL_RCC_TSC_RELEASE_RESET(); __HAL_RCC_TSC_RELEASE_RESET();
priv->all_channels_mask = 0;
for (int gi = 0; gi < 8; gi++) { for (int gi = 0; gi < 8; gi++) {
const uint8_t cap = priv->cfg.group_scaps[gi]; const uint8_t cap = priv->cfg.group_scaps[gi];
const uint8_t ch = priv->cfg.group_channels[gi]; const uint8_t ch = priv->cfg.group_channels[gi];
@ -132,6 +134,10 @@ error_t UTOUCH_init(Unit *unit)
else { else {
dbg_touch("TSC ch @ %s", rsc_get_name(r)); dbg_touch("TSC ch @ %s", rsc_get_name(r));
if (priv->cfg.interlaced) {
// interlaced - only update the mask beforehand
priv->all_channels_mask |= bit;
} else {
// channels are configured individually when read. // channels are configured individually when read.
// we prepare bitmaps to use for the read groups (all can be read in at most 3 steps) // 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->channels_phase[phasenum] |= bit; // this is used for the channel selection register
@ -140,6 +146,7 @@ error_t UTOUCH_init(Unit *unit)
} }
} }
} }
}
// common TSC config // common TSC config
TSC->CR = TSC->CR =
@ -154,7 +161,9 @@ error_t UTOUCH_init(Unit *unit)
TSC->CR |= ((priv->cfg.spread_deviation - 1) << TSC_CR_SSD_Pos) | TSC_CR_SSE; 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 // iofloat is used for discharging
@ -162,16 +171,22 @@ error_t UTOUCH_init(Unit *unit)
TSC->IER = TSC_IER_EOAIE | TSC_IER_MCEIE; TSC->IER = TSC_IER_EOAIE | TSC_IER_MCEIE;
irqd_attach(TSC, UTOUCH_HandleIrq, unit); irqd_attach(TSC, UTOUCH_HandleIrq, unit);
if (!priv->cfg.interlaced) {
dbg_touch("TSC phases:"); dbg_touch("TSC phases:");
priv->all_channels_mask = 0;
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
priv->all_channels_mask |= priv->channels_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]);
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->status = UTSC_STATUS_BUSY; // first loop ...
priv->next_phase = 0; priv->next_phase = 0;
UTOUCH_updateTick(unit);
// starts in the tick callback
return E_SUCCESS; return E_SUCCESS;
} }

@ -11,7 +11,7 @@
#include "unit_base.h" #include "unit_base.h"
#define TSC_DEBUG 1 #define TSC_DEBUG 0
#if TSC_DEBUG #if TSC_DEBUG
#define dbg_touch(f,...) dbg(f,##__VA_ARGS__) #define dbg_touch(f,...) dbg(f,##__VA_ARGS__)

@ -149,7 +149,7 @@ void UTOUCH_writeIni(Unit *unit, IniWriter *iw)
iw_entry(iw, "ss-clock-prediv", "%d", (int)priv->cfg.ss_presc); iw_entry(iw, "ss-clock-prediv", "%d", (int)priv->cfg.ss_presc);
iw_cmt_newline(iw); 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_entry(iw, "interlaced-pads", str_yn(priv->cfg.interlaced));
iw_cmt_newline(iw); iw_cmt_newline(iw);

Loading…
Cancel
Save