149 lines
5.4 KiB
C
149 lines
5.4 KiB
C
|
/*
|
||
|
* FreeTouch, a QTouch-compatible library - tested on ATSAMD21 only!
|
||
|
* The MIT License (MIT)
|
||
|
*
|
||
|
* Copyright (c) 2017 Limor 'ladyada' Fried for Adafruit Industries
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
* of this software and associated documentation files (the "Software"), to deal
|
||
|
* in the Software without restriction, including without limitation the rights
|
||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
* copies of the Software, and to permit persons to whom the Software is
|
||
|
* furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
|
* THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#include "adafruit_ptc.h"
|
||
|
#include "pinmux.h"
|
||
|
|
||
|
static void sync_config(Ptc const* module_inst) {
|
||
|
while (module_inst->CONTROLB.bit.SYNCFLAG) ;
|
||
|
}
|
||
|
|
||
|
void adafruit_ptc_get_config_default(struct adafruit_ptc_config *config) {
|
||
|
config->pin = 0xff;
|
||
|
config->yline = -1;
|
||
|
config->oversample = OVERSAMPLE_4;
|
||
|
config->seriesres = RESISTOR_0;
|
||
|
config->freqhop = FREQ_MODE_NONE;
|
||
|
config->compcap = 0x2000;
|
||
|
config->intcap = 0x3F;
|
||
|
}
|
||
|
|
||
|
void adafruit_ptc_init(Ptc* module_inst, struct adafruit_ptc_config const* config) {
|
||
|
struct system_pinmux_config pinmux_config;
|
||
|
system_pinmux_get_config_defaults(&pinmux_config);
|
||
|
pinmux_config.mux_position = 0x1;
|
||
|
pinmux_config.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
|
||
|
system_pinmux_pin_set_config(config->pin, &pinmux_config);
|
||
|
|
||
|
sync_config(module_inst);
|
||
|
module_inst->CONTROLA.bit.ENABLE = 0;
|
||
|
sync_config(module_inst);
|
||
|
|
||
|
module_inst->UNK4C04.reg &= 0xF7; //MEMORY[0x42004C04] &= 0xF7u;
|
||
|
module_inst->UNK4C04.reg &= 0xFB; //MEMORY[0x42004C04] &= 0xFBu;
|
||
|
module_inst->UNK4C04.reg &= 0xFC; //MEMORY[0x42004C04] &= 0xFCu;
|
||
|
sync_config(module_inst);
|
||
|
module_inst->FREQCONTROL.reg &= 0x9F; //MEMORY[0x42004C0C] &= 0x9Fu;
|
||
|
sync_config(module_inst);
|
||
|
module_inst->FREQCONTROL.reg &= 0xEF; //MEMORY[0x42004C0C] &= 0xEFu;
|
||
|
sync_config(module_inst);
|
||
|
module_inst->FREQCONTROL.bit.SAMPLEDELAY = 0; //MEMORY[0x42004C0C] &= 0xF0u;
|
||
|
module_inst->CONTROLC.bit.INIT = 1; //MEMORY[0x42004C05] |= 1u;
|
||
|
module_inst->CONTROLA.bit.RUNINSTANDBY = 1; //MEMORY[0x42004C00] |= 4u;
|
||
|
sync_config(module_inst);
|
||
|
module_inst->INTDISABLE.bit.WCO = 1;
|
||
|
sync_config(module_inst);
|
||
|
module_inst->INTDISABLE.bit.EOC = 1;
|
||
|
sync_config(module_inst);
|
||
|
|
||
|
// enable the sensor, only done once per line
|
||
|
if (config->yline < 8) {
|
||
|
sync_config(module_inst);
|
||
|
module_inst->YENABLEL.reg |= 1 << config->yline;
|
||
|
sync_config(module_inst);
|
||
|
} else if (config->yline < 16) {
|
||
|
module_inst->YENABLEH.reg |= 1 << (config->yline - 8);
|
||
|
}
|
||
|
|
||
|
sync_config(module_inst);
|
||
|
module_inst->CONTROLA.bit.ENABLE = 1;
|
||
|
sync_config(module_inst);
|
||
|
}
|
||
|
|
||
|
void adafruit_ptc_start_conversion(Ptc* module_inst, struct adafruit_ptc_config const* config) {
|
||
|
module_inst->CONTROLA.bit.RUNINSTANDBY = 1;
|
||
|
sync_config(module_inst);
|
||
|
module_inst->CONTROLA.bit.ENABLE = 1;
|
||
|
sync_config(module_inst);
|
||
|
module_inst->INTDISABLE.bit.WCO = 1;
|
||
|
sync_config(module_inst);
|
||
|
module_inst->INTFLAGS.bit.WCO = 1;
|
||
|
sync_config(module_inst);
|
||
|
module_inst->INTFLAGS.bit.EOC = 1;
|
||
|
sync_config(module_inst);
|
||
|
|
||
|
// set up pin!
|
||
|
sync_config(module_inst);
|
||
|
if (config->yline < 8) {
|
||
|
module_inst->YSELECTL.reg = 1 << config->yline;
|
||
|
} else {
|
||
|
module_inst->YSELECTL.reg = 0;
|
||
|
}
|
||
|
|
||
|
if (config->yline > 7) {
|
||
|
module_inst->YSELECTH.reg = 1 << (config->yline - 8);
|
||
|
} else {
|
||
|
module_inst->YSELECTH.reg = 0;
|
||
|
}
|
||
|
|
||
|
sync_config(module_inst);
|
||
|
// set up sense resistor
|
||
|
module_inst->SERRES.bit.RESISTOR = config->seriesres;
|
||
|
sync_config(module_inst);
|
||
|
// set up prescalar
|
||
|
module_inst->CONVCONTROL.bit.ADCACCUM = config->oversample;
|
||
|
sync_config(module_inst);
|
||
|
// set up freq hopping
|
||
|
if (config->freqhop == FREQ_MODE_NONE) {
|
||
|
module_inst->FREQCONTROL.bit.FREQSPREADEN = 0;
|
||
|
module_inst->FREQCONTROL.bit.SAMPLEDELAY = 0;
|
||
|
} else {
|
||
|
module_inst->FREQCONTROL.bit.FREQSPREADEN = 1;
|
||
|
module_inst->FREQCONTROL.bit.SAMPLEDELAY = config->hops;
|
||
|
}
|
||
|
// set up compensation cap + int (?) cap
|
||
|
sync_config(module_inst);
|
||
|
module_inst->COMPCAPL.bit.VALUE = config->compcap & 0xFF;
|
||
|
module_inst->COMPCAPH.bit.VALUE = (config->compcap>>8) & 0x3F;
|
||
|
sync_config(module_inst);
|
||
|
module_inst->INTCAP.bit.VALUE = config->intcap & 0x3F;
|
||
|
sync_config(module_inst);
|
||
|
|
||
|
module_inst->BURSTMODE.reg = 0xA4;
|
||
|
sync_config(module_inst);
|
||
|
|
||
|
module_inst->CONVCONTROL.bit.CONVERT = 1;
|
||
|
sync_config(module_inst);
|
||
|
}
|
||
|
|
||
|
bool adafruit_ptc_is_conversion_finished(Ptc* module_inst) {
|
||
|
return module_inst->CONVCONTROL.bit.CONVERT == 0;
|
||
|
}
|
||
|
|
||
|
uint16_t adafruit_ptc_get_conversion_result(Ptc* module_inst) {
|
||
|
sync_config(module_inst);
|
||
|
return module_inst->RESULT.reg;
|
||
|
}
|