Created
June 16, 2012 11:25
-
-
Save robertinant/2941071 to your computer and use it in GitHub Desktop.
MSP430 Energia CapTouch library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
************************************************************************ | |
* CapTouch.cpp | |
* | |
* Energia core files for MSP430 | |
* Copyright (c) 2012 Robert Wessels. All right reserved. | |
* | |
* | |
*********************************************************************** | |
Copyright (c) 2012 Robert Wessels. All right reserved. | |
This library is free software; you can redistribute it and/or | |
modify it under the terms of the GNU Lesser General Public | |
License as published by the Free Software Foundation; either | |
version 2.1 of the License, or (at your option) any later version. | |
This library is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
Lesser General Public License for more details. | |
You should have received a copy of the GNU Lesser General Public | |
License along with this library; if not, write to the Free Software | |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
*/ | |
#include "Energia.h" | |
#include "CapTouch.h" | |
// Initialize Class Variables ////////////////////////////////////////////////// | |
// Constructors //////////////////////////////////////////////////////////////// | |
CapTouch::CapTouch() | |
{ | |
} | |
// Private Methods ////////////////////////////////////////////////////////////// | |
CapTouch::pin* CapTouch::find(uint8_t pnum) | |
{ | |
pin *q; | |
for(q = p; q != NULL; q = q->link) | |
if(q->pinNumber == pnum) break; | |
return q; | |
} | |
// Public Methods ////////////////////////////////////////////////////////////// | |
void CapTouch::setThresholdHiRes(uint8_t pnum, uint16_t threshold) | |
{ | |
pin *q = find(pnum); | |
q->threshold_hires = threshold; | |
} | |
void CapTouch::setThresholdLowRes(uint8_t pnum, uint16_t threshold) | |
{ | |
pin *q = find(pnum); | |
q->threshold_lowres = threshold; | |
} | |
uint16_t CapTouch::getBaseCntHiRes(uint8_t pnum) | |
{ | |
pin *q = find(pnum); | |
return q->baseCount_hires; | |
} | |
void CapTouch::add(uint8_t pnum) | |
{ | |
volatile uint16_t *sel; | |
volatile uint16_t *sel2; | |
pin *q,*t; | |
/* We need to find out if the pin is PIN OSC capable before we add it to the list */ | |
/* Find out if the pin is on a port we know of */ | |
uint8_t port = digitalPinToPort(pnum); | |
/* Not a port we know of */ | |
if (port == NOT_A_PORT) return; | |
/* Get the port function select 2 register address */ | |
sel2 = portSel2Register(port); | |
/* If there is no sel2 register then this port does not have PIN OSC */ | |
if (sel2 == NOT_A_PORT) return; | |
/* Get the bit mask for this pin */ | |
uint8_t bit = digitalPinToBitMask(pnum); | |
/* Get the port function select register address */ | |
sel = portSelRegister(port); | |
if (p == NULL) { | |
/* first element in the list */ | |
p = new pin; | |
p->link = NULL; | |
t = p; | |
} else { | |
q = p; | |
while (q->link != NULL) | |
q = q->link; | |
t = new pin; | |
t->link = NULL; | |
q->link = t; | |
} | |
t->pinNumber = pnum; | |
t->sel = sel; | |
t->sel2 = sel2; | |
t->bit = bit; | |
/* set initial base line */ | |
t->baseCount_lowres = measure(pnum, TOUCH_RAW); | |
t->baseCount_lowres = (t->baseCount_lowres + measure(pnum, TOUCH_RAW)) / 2; | |
t->baseCount_lowres = (t->baseCount_lowres + measure(pnum, TOUCH_RAW)) / 2; | |
t->baseCount_lowres = (t->baseCount_lowres + measure(pnum, TOUCH_RAW)) / 2; | |
t->baseCount_hires = measure(pnum, TOUCH_RAW_HIRES); | |
t->baseCount_hires = (t->baseCount_hires + measure(pnum, TOUCH_RAW_HIRES)) / 2; | |
t->baseCount_hires = (t->baseCount_hires + measure(pnum, TOUCH_RAW_HIRES)) / 2; | |
t->baseCount_hires = (t->baseCount_hires + measure(pnum, TOUCH_RAW_HIRES)) / 2; | |
t->threshold_hires = 150; | |
t->threshold_lowres = 150; | |
} | |
uint8_t CapTouch::count(void) | |
{ | |
pin *q; | |
int c=0; | |
for (q=p ; q != NULL ; q = q->link) | |
c++; | |
return c; | |
} | |
uint16_t CapTouch::measure(uint8_t pnum, uint8_t mode) | |
{ | |
pin *q; | |
uint8_t SRSave; | |
uint8_t SelSave, Sel2Save; | |
uint8_t BCSCTL1Save, DCOCTLSave, BCSCTL2Save; | |
uint16_t WDTCTLSave; | |
uint16_t TA0CTLSave, TA0CCTL1Save, TA0CCR1Save; | |
uint16_t delta_count, ret_val; | |
q = find(pnum); | |
if(!q) return 0; | |
/* Save context */ | |
SRSave = __read_status_register(); | |
WDTCTLSave = WDTCTL; | |
WDTCTLSave &= 0x00FF; | |
WDTCTLSave |= WDTPW; | |
TA0CTLSave = TA0CTL; | |
TA0CCTL1Save = TA0CCTL1; | |
TA0CCR1Save = TA0CCR1; | |
SelSave = *q->sel; | |
Sel2Save = *q->sel2; | |
/* Set bit in pin function select register to select PIN OSC */ | |
*q->sel2 |= q->bit; | |
*q->sel &= ~q->bit; | |
BCSCTL1Save = BCSCTL1; | |
BCSCTL2Save = BCSCTL2; | |
DCOCTLSave = DCOCTL; | |
/* TODO: Is it better to use ACLK? | |
* Drop SMCLK down to 125 KHz to maximize the gate time. | |
* If we run @ 16 MHz then we can not configure a long enough gate time | |
* to do accurate measurement */ | |
BCSCTL1 = CALBC1_1MHZ; | |
DCOCTL = CALDCO_1MHZ; | |
BCSCTL2 |= DIVS_3; | |
/* TA0 in continous mode and clock source as INCLK. | |
* INCLK comes from the PIN OSC cricuit. See PIN OSC clock tree | |
* in section "Pin Oscillator" of Users Guide. | |
* Pins without external load show typical oscillation frequencies of 1 MHz to 3 MHz. */ | |
TA0CTL = TASSEL_3 + MC_2; | |
/* Capture mode, capture on rising and falling edge, input as GND | |
* Later on we will XOR with CCIS0 to induce a s/w capture. */ | |
TA0CCTL1 = CM_3 + CCIS_2 + CAP; | |
/* Enable Watchdog interrupt */ | |
IE1 |= WDTIE; | |
/* Interval mode + SMCLK + /8192 for hires and /512 for lowres */ | |
if(mode == TOUCH_RAW_HIRES || mode == TOUCH_BUTTON_HIRES || mode == TOUCH_DELTA_HIRES) | |
WDTCTL = (WDTPW + WDTTMSEL + GATE_WDT_SMCLK + WDTp_GATE_8192); | |
else | |
WDTCTL = (WDTPW + WDTTMSEL + GATE_WDT_SMCLK + WDTp_GATE_512); | |
/* Clear Timer_A TAR */ | |
TA0CTL |= TACLR; | |
/* Wait for WDT interrupt in LPM3 and global interrupts enables */ | |
__bis_status_register(LPM0_bits + GIE); | |
/* Capture initiated by Software . | |
* Worse case count = min PIN OSC Freq / SMCLK / 8192 | |
* = for hires -> 1 MHz / (125 KHz / 8192 ) = 65536 | |
* = for regular -> 1 MHz / (125 KHz / 512 ) = 4096 | |
* In this configuration a hires measurement takes ~65 ms and a lowres measurement takes ~4 ms */ | |
TA0CCTL1 ^= CCIS0; | |
q->measuredCount = TA0CCR1; | |
/* Stop watchdog timer */ | |
WDTCTL = WDTPW + WDTHOLD; | |
/* calculate the return for the various modes */ | |
switch(mode) { | |
case TOUCH_RAW: | |
case TOUCH_RAW_HIRES: | |
ret_val = q->measuredCount; | |
break; | |
case TOUCH_BUTTON: | |
if(q->baseCount_lowres < q->measuredCount) { | |
q->baseCount_lowres = q->baseCount_lowres / 2 + q->measuredCount / 2; | |
ret_val = 0; | |
} else { | |
delta_count = q->baseCount_lowres - q->measuredCount; | |
ret_val = (delta_count > q->threshold_lowres) ? 1:0; | |
} | |
break; | |
case TOUCH_BUTTON_HIRES: | |
if(q->baseCount_hires < q->measuredCount) { | |
q->baseCount_hires = q->baseCount_hires / 2 + q->measuredCount / 2; | |
ret_val = 0; | |
} else { | |
delta_count = q->baseCount_hires - q->measuredCount; | |
ret_val = (delta_count > q->threshold_hires) ? 1:0; | |
} | |
break; | |
case TOUCH_DELTA: | |
ret_val = q->baseCount_lowres - q->measuredCount; | |
break; | |
case TOUCH_DELTA_HIRES: | |
if(q->baseCount_hires < q->measuredCount) | |
q->baseCount_hires = q->baseCount_hires / 2 + q->measuredCount / 2; | |
ret_val = q->baseCount_hires - q->measuredCount; | |
break; | |
default: | |
ret_val = 0; | |
break; | |
} | |
/* Restore context */ | |
__bis_SR_register(SRSave); | |
*q->sel = SelSave; | |
*q->sel2 = Sel2Save; | |
WDTCTL = WDTCTLSave; | |
TA0CTL = TA0CTLSave; | |
TA0CCTL1 = TA0CCTL1Save; | |
TA0CCR1 = TA0CCR1Save; | |
BCSCTL1 = BCSCTL1Save; | |
BCSCTL2 = BCSCTL2Save; | |
DCOCTL = DCOCTLSave; | |
return ret_val; | |
} | |
CapTouch Touch = CapTouch(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
************************************************************************ | |
* CapTouch.h | |
* | |
* Energia core files for MSP430 | |
* Copyright (c) 2012 Robert Wessels. All right reserved. | |
* | |
* | |
*********************************************************************** | |
Copyright (c) 2012 Robert Wessels. All right reserved. | |
This library is free software; you can redistribute it and/or | |
modify it under the terms of the GNU Lesser General Public | |
License as published by the Free Software Foundation; either | |
version 2.1 of the License, or (at your option) any later version. | |
This library is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
Lesser General Public License for more details. | |
You should have received a copy of the GNU Lesser General Public | |
License along with this library; if not, write to the Free Software | |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
*/ | |
#ifndef CapTouch_h | |
#define CapTouch_h | |
#include <inttypes.h> | |
#define GATE_WDT_ACLK 0x0004 | |
#define GATE_WDT_SMCLK 0x0000 | |
#define WDTp_GATE_32768 0x0000 // watchdog source/32768 | |
#define WDTp_GATE_8192 0x0001 // watchdog source/8192 | |
#define WDTp_GATE_512 0x0002 // watchdog source/512 | |
#define WDTp_GATE_64 0x0003 // watchdog source/64 | |
#define TOUCH_RAW 0 | |
#define TOUCH_BUTTON 1 | |
#define TOUCH_DELTA 2 | |
#define TOUCH_RAW_HIRES 3 | |
#define TOUCH_BUTTON_HIRES 4 | |
#define TOUCH_DELTA_HIRES 5 | |
class CapTouch { | |
private: | |
struct pin { | |
uint8_t pinNumber; | |
uint8_t bit; | |
uint16_t threshold_lowres; | |
uint16_t threshold_hires; | |
uint16_t baseCount_lowres; | |
uint16_t baseCount_hires; | |
uint16_t measuredCount; | |
volatile uint16_t *sel; | |
volatile uint16_t *sel2; | |
pin *link; | |
} *p; | |
pin* find(uint8_t pnum); | |
public: | |
CapTouch(); | |
void add(uint8_t pnum); | |
void setThresholdLowRes(uint8_t pnum, uint16_t threshold); | |
void setThresholdHiRes(uint8_t pnum, uint16_t threshold); | |
uint16_t getBaseCntHiRes(uint8_t pnum); | |
uint8_t count(void); | |
uint16_t measure(uint8_t pnum, uint8_t mode = TOUCH_RAW); | |
}; | |
extern CapTouch Touch; | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
empty |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment