A QTouch-compatible library
adafruit / adafruit_freetouch Goto Github PK
View Code? Open in Web Editor NEWA QTouch-compatible library
A QTouch-compatible library
FreeTouch as used in libraries
During a measurement, FreeTouch makes many reads to some Read-Synchronized registers in the PTC, and does so without the synchronizing read-request sequence. Because the PTC is clocked slower than the system clock, these reads cause a significant stall (~185µs each) of the Peripheral Bridge C, stalling all access to the other peripherals on the same bridge.
If DMA is trying access any of those peripherals (like the DAC or ADC) - then it will be stalled. At ~185µs stall, this is enough to lose several samples at audio rates, causing significant distortion.
This bridge stall can be induced with any peripheral on the C bridge that has a Read Synchronized register. To induce the stall:
a) the peripheral needs to be clocked with a clock slower than GCLK0
b) make the register read without first performing the READREQ sequence
Note that if the peripheral is clocked via GLCK0 - as most are by default - then a read to a Read Synchronized register made without the READREQ sequence will still stall the bridge, but it will be for a very short time (docs. imply <8 clocks). This won't materially affect DMA audio.
However, the PTC must be clocked at 4MHz, and this is achieved by setting GCLK1 to use the 8MHz clock source and dividing down. FreeTouch sets this up. And then FreeTouch makes reads that stall the bridge.
This sketch demonstrates the issue on a Circuit Playground Express: https://gist.github.com/mzero/89955e14d41d7e37a439ba806746f632
The sketch uses DMA drive audio out to the DAC "in the background", only using CPU during DMA interrupts to compute the next buffer of samples.
In the foreground (in loop()
) the sketch can call FreeTouch ever 50ms to demonstrate the issue. It can also demonstrate the issue by directly accessing the PTC, or reading TC3 configured to cause the issue. The distortion is plainly audible.
The main issue is in the code:
bool adafruit_ptc_is_conversion_finished(Ptc *module_inst) {
return module_inst->CONVCTRL.bit.CONVERT == 0;
}
uint16_t adafruit_ptc_get_conversion_result(Ptc *module_inst) {
sync_config(module_inst);
return module_inst->RESULT.reg;
}
Both CONVERT
and RESULT
appear to be Read Synchronized registers. (Note: the sync_config
call does not implement the read request sequence and does not sync reads.)
In the the Circuit Playground version, this code is:
uint16_t Adafruit_CPlay_FreeTouch::startPtcAcquire(void) {
ptcConfigIOpin();
ptcAcquire();
while (QTOUCH_PTC->CONVCONTROL.bit.CONVERT) {
yield();
}
sync_config();
uint16_t result = QTOUCH_PTC->RESULT.reg;
return result;
}
This makes the issue plainly bad: The CONVERT
read is done in a spin loop... causing stalls lasting over 8ms during which only a fraction of DMA operations get in.
It is clear from the code that the READREQ
register for the PTC hasn't been sleuthed out yet. There are two other SAM D21 modules with READREQ
functionality (RTC & TC timers) and one imagines that PTC's is similarly constructed in layout and operation. Some more reverse engineering of the PTC is in order.
Hi,
Could you write a license?
Hi! I have a bit of a problem.
I am trying to make some device that would utilize the touch keys in order to control it. The mcu I am trying to use is the SAMD21E15 one but I've had the exact same problem using your trinket m0.
(I am using the oversample of 8, rest is set as in the example project)
So my problems started right at the beginning when I just ran the freetouch example project. For my device I'd need for it to be able to recognize all the touch keys at once (that mcu has only 6 pins that seem to work but that'd be enough for me) so to eg. do one action when there's only one touched, another action when two of them are touched etc.
However when I ran the freetouch example project it looks like a totally impossible task. The problems start appearing right after I touch only two of them.
So when I am not touching any of the copper plates I'm using as sensors the readings vary between 150 and 250 depending on the pin. When I touch only one of them the value for that pin rises up to about 1000 which is plenty enough to set a simple action trigger when the value reaches eg. 500. But when I touch two of them then I am not getting the values of 1000 on both of them, instead it's somewhere around 400 for each pin. The situation gets even worse when I touch 3 plates as then the values read can be used to determine if the button is touched no more - all 3 of the readings drop close to the 250 base reading so it seems impossible to set any threshold to have 3 buttons activated at once and it's just half of the pins I wanted to utilise.
I can't believe that this is a proper working setup. Do I need to configure the freetouch pins in some special ways? Changing oversample and series resistor values gets it even worse as the readings for 3 pins touched at once drop below the base value, with any other resistor set they drop to less than a 100.
I am thinking that maybe this isn't as simple as just connecting some copper plates into the pins and it needs some more parts in order to get it to work properly?
Thanks in advance
Correct me if I am wrong, but there doesn't seem to be support for mutual capacitance setups (using both X and Y lines) in the library. Is this something I am missing or is this not currently possible to use?
Adafruit_FreeTouch/samd21_ptc_component.h
Line 31 in facf05d
Arduino/libraries/Adafruit_FreeTouch_Library/samd21_ptc_component.h:31:10: fatal error: sam.h: No such file or directory
#include "sam.h"
^~~~~~~
compilation terminated.
while trying to use library for the this example:
https://learn.adafruit.com/adafruit-neo-trinkey/arduino-example
I tried to sift through the QTouch user guide in order to understand some of the things at play in the PTC but I'm not really smarter than before.
What I'm mostly interested in is what these functions are doing, the concept behind them and how they are practically used.
For example what is a compensation capacitor, what do I do with that and how? Some insight especially for the functions below would be much appericated!
void setSeriesResistor(series_resistor_t res);
void setFreqHopping(freq_mode_t fh, freq_hop_t hops = FREQ_HOP_1);
void setCompCap(uint16_t cc);
void setIntCap(uint8_t ic);
Arduino board: Metro M0 Express
Arduino IDE version (found in Arduino -> About Arduino menu): 1.8.13
List the steps to reproduce the problem below (if possible attach a sketch or
copy the sketch code in too):
I am trying to set up multiple touch sensitive buttons, upon running the example code it seems as though pressing any 1 touch sense work as intended, however if I touch 2 or more of them, the number seems to be unchanged or even to drop. Is there a work around for this? or is this a hardware issue?
local variable m is of unsigned type:
Adafruit_FreeTouch.cpp: In member function 'uint16_t Adafruit_FreeTouch::measure()':
Adafruit_FreeTouch.cpp:111:9: warning: comparison is always false due to limited range of data type [-Wtype-limits]
if (m == -1)
Seems that lots of files from the asf4/samd21 folder are missing?
Build options changed, rebuilding all In file included from /home/andreas/Arduino/libraries/Adafruit_FreeTouch_Library/adafruit_ptc.h:32:0, from /home/andreas/Arduino/libraries/Adafruit_FreeTouch_Library/Adafruit_FreeTouch.h:5, from /home/andreas/Arduino/Blink/Blink.ino:1: /home/andreas/Arduino/libraries/Adafruit_FreeTouch_Library/samd21_ptc_component.h:31:22: fatal error: compiler.h: No such file or directory #include "compiler.h" ^ compilation terminated. exit status 1 Error compiling for board Adafruit Trinket M0.
Hi
Do you plan to support the X lines?
Thanks
Lack of support for M4 (specifically AT SAM D51) is blocking touchio support in CircuitPython: adafruit/circuitpython#268
I'd really like to have touch inputs on the Adafruit M4-based boards, but the data sheet basically just says "use qtouch"; how can I help?
Hi
I'm trying to use the freetouch library with a sparkfun samd21 card and I can not make it work
if I charge the playground M0 firmware it works ok
Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.