Fork of Kojto's library with bugfixes: * added PTC2/TSI0_CH15 pinmapping for KL25 and KL46 MCUs * Fixed readDistance() function

Fork of tsi_sensor by Martin Kojtal

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tsi_sensor.cpp Source File

tsi_sensor.cpp

00001 /* Freescale Semiconductor Inc.
00002  * mbed Microcontroller Library
00003  * (c) Copyright 2014 ARM Limited.
00004  *
00005  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00006  * and associated documentation files (the "Software"), to deal in the Software without
00007  * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00008  * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in all copies or
00012  * substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00015  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00016  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00017  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00018  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00019  */
00020 
00021 #include "mbed.h"
00022 #include "tsi_sensor.h"
00023 
00024 void tsi_irq(void);
00025 TSIAnalogSlider *TSIAnalogSlider::_instance;
00026 
00027 TSIAnalogSlider::TSIAnalogSlider(PinName pin0, PinName pin1, uint32_t range): _elec0(pin0), _elec1(pin1), _range(range) {
00028     initObject();
00029 }
00030 TSIAnalogSlider::TSIAnalogSlider(uint32_t elec0, uint32_t elec1,
00031                                  uint32_t range)
00032 : _elec0(elec0), _elec1(elec1), _range(range) {
00033     initObject();
00034 }
00035 
00036 void TSIAnalogSlider::initObject(void) {    
00037     _instance = this;
00038     _current_elec = &_elec0;
00039     SIM->SCGC5 |= SIM_SCGC5_TSI_MASK;
00040 
00041     TSI0->GENCS |= (TSI_GENCS_ESOR_MASK | TSI_GENCS_MODE(0) | TSI_GENCS_REFCHRG(4)
00042                    | TSI_GENCS_DVOLT(0) | TSI_GENCS_EXTCHRG(7) | TSI_GENCS_PS(4)
00043                    | TSI_GENCS_NSCN(11) | TSI_GENCS_TSIIEN_MASK | TSI_GENCS_STPE_MASK);
00044     TSI0->GENCS |= TSI_GENCS_TSIEN_MASK;
00045 
00046     NVIC_SetVector(TSI0_IRQn, (uint32_t)&tsi_irq);
00047     NVIC_EnableIRQ(TSI0_IRQn);
00048 
00049     selfCalibration();
00050 }
00051 
00052 static void initBaseline(TSIElectrode& elec)
00053 {
00054     uint32_t channel0 = elec.getChannel();
00055     TSI0->DATA = ((channel0 << TSI_DATA_TSICH_SHIFT) );
00056     TSI0->DATA |= TSI_DATA_SWTS_MASK;
00057     while(!(TSI0->GENCS & TSI_GENCS_EOSF_MASK));
00058     TSI0->GENCS |= TSI_GENCS_EOSF_MASK;
00059     elec.setBaseline(TSI0->DATA & TSI_DATA_TSICNT_MASK);
00060 }
00061 
00062 void TSIAnalogSlider::selfCalibration(void)
00063 {
00064     TSI0->GENCS |= TSI_GENCS_EOSF_MASK;      // Clear End of Scan Flag
00065     TSI0->GENCS &= ~TSI_GENCS_TSIEN_MASK;    // Disable TSI module
00066 
00067     uint32_t trigger_backup;
00068     if(TSI0->GENCS & TSI_GENCS_STM_MASK) {     // Back-up TSI Trigger mode from Application
00069         trigger_backup = 1;
00070     } else {
00071         trigger_backup = 0;
00072     }
00073 
00074     TSI0->GENCS &= ~TSI_GENCS_STM_MASK;    // Use SW trigger
00075     TSI0->GENCS &= ~TSI_GENCS_TSIIEN_MASK; // Enable TSI interrupts
00076     TSI0->GENCS |= TSI_GENCS_TSIEN_MASK;   // Enable TSI module
00077 
00078     initBaseline(_elec0);
00079     initBaseline(_elec1);
00080 
00081     TSI0->DATA = ((_elec0.getChannel() << TSI_DATA_TSICH_SHIFT));
00082 
00083     TSI0->GENCS &= ~TSI_GENCS_TSIEN_MASK;    // Disable TSI module
00084     TSI0->GENCS |= TSI_GENCS_TSIIEN_MASK;     // Enale TSI interrupt
00085     if (trigger_backup) {                     // Restore trigger mode
00086         TSI0->GENCS |= TSI_GENCS_STM_MASK;
00087     } else {
00088         TSI0->GENCS &= ~TSI_GENCS_STM_MASK;
00089     }
00090 
00091     TSI0->GENCS |= TSI_GENCS_TSIEN_MASK;     // Enable TSI module
00092     TSI0->DATA |= TSI_DATA_SWTS_MASK;
00093 }
00094 
00095 
00096 void TSIAnalogSlider::sliderRead(void ) {
00097     if (_scan_in_progress) {
00098         _scan_in_progress = 0;
00099         uint32_t delta0 = _elec0.getDelta();
00100         uint32_t delta1 = _elec1.getDelta();
00101 
00102         if ((delta0 > _elec0.getThreshold()) || (delta1 > _elec1.getThreshold())) {
00103             uint32_t perc_pos0 = (delta0 * 100) / (delta0 + delta1);
00104             uint32_t perc_pos1 = (delta1 * 100) / (delta0 + delta1);
00105             setSliderPercPosition(0, perc_pos0);
00106             setSliderPercPosition(1, perc_pos1);
00107             uint32_t dist_pos0 = (perc_pos0 * _range) / 100;
00108             uint32_t dist_pos1 = (perc_pos1 * _range) / 100;
00109             setSliderDisPosition(0, dist_pos0);
00110             setSliderDisPosition(1, dist_pos1);
00111 
00112             setAbsolutePosition(((100 - perc_pos0) + perc_pos1) / 2);
00113             setAbsoluteDistance(((_range - dist_pos0) + dist_pos1) / 2);
00114         } else {
00115             setSliderPercPosition(0, 0);
00116             setSliderPercPosition(1, 0);
00117             setSliderDisPosition(0, 0);
00118             setSliderDisPosition(1, 0);
00119             setAbsolutePosition(0);
00120             setAbsoluteDistance(0);
00121         }
00122     }
00123 }
00124 
00125 float TSIAnalogSlider::readPercentage() {
00126     sliderRead();
00127     return (float)getAbsolutePosition() / 100.0;
00128 }
00129 
00130 uint32_t TSIAnalogSlider::readDistance() {
00131     sliderRead();
00132     return getAbsoluteDistance();
00133 }
00134 
00135 static void changeElectrode(TSIAnalogSlider *analog_slider)
00136 {
00137     TSIElectrode* elec = analog_slider->getCurrentElectrode();
00138     uint32_t signal = (TSI0->DATA & TSI_DATA_TSICNT_MASK);
00139     elec->setSignal(signal);
00140 
00141     TSIElectrode *next_elec =  analog_slider->getNextElectrode(elec);
00142 
00143     analog_slider->setCurrentElectrode(next_elec);
00144     TSI0->DATA = ((next_elec->getChannel() << TSI_DATA_TSICH_SHIFT) );
00145     TSI0->DATA |= TSI_DATA_SWTS_MASK;
00146 }
00147 
00148 
00149 void tsi_irq(void)
00150 {
00151     TSIAnalogSlider *analog_slider = TSIAnalogSlider::getInstance();
00152     analog_slider->setScan(1);
00153     TSI0->GENCS |= TSI_GENCS_EOSF_MASK; // Clear End of Scan Flag
00154     changeElectrode(analog_slider);
00155 }