A library for Freescale MCU which contain TSI peripheral, just for Kinetis L version. Because they use "lighter" version of TSI peripheral.
Dependents: kl25z-tinyshell-demo tsi_slider_light_senso_LED frdm_tsi_slider_led_blend demo_slider ... more
This library is "fork" of the TSI library created by the mbed team.
Revision 0:9331e373c138, committed 2014-02-22
- Comitter:
- Kojto
- Date:
- Sat Feb 22 11:07:29 2014 +0000
- Child:
- 1:8a2098a10330
- Commit message:
- the initial version of TSI sensor library. It contains TSI electrode and TSI Analog slider objects.
Changed in this revision
tsi_sensor.cpp | Show annotated file Show diff for this revision Revisions of this file |
tsi_sensor.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tsi_sensor.cpp Sat Feb 22 11:07:29 2014 +0000 @@ -0,0 +1,148 @@ +/* Freescale Semiconductor Inc. + * mbed Microcontroller Library + * (c) Copyright 2014 ARM Limited. + * + * 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 "mbed.h" +#include "TSISensor.h" + +void tsi_irq(void); +TSIAnalogSlider *TSIAnalogSlider::_instance; + +TSIAnalogSlider::TSIAnalogSlider(TSIElectrode& elec0, TSIElectrode& elec1, + uint32_t range) +: _elec0(elec0), _elec1(elec1), _range(range) { + _instance = this; + _current_elec = &elec0; + SIM->SCGC5 |= SIM_SCGC5_TSI_MASK; + + TSI0->GENCS |= (TSI_GENCS_ESOR_MASK | TSI_GENCS_MODE(0) | TSI_GENCS_REFCHRG(4) + | TSI_GENCS_DVOLT(0) | TSI_GENCS_EXTCHRG(7) | TSI_GENCS_PS(4) + | TSI_GENCS_NSCN(11) | TSI_GENCS_TSIIEN_MASK | TSI_GENCS_STPE_MASK); + TSI0->GENCS |= TSI_GENCS_TSIEN_MASK; + + NVIC_SetVector(TSI0_IRQn, (uint32_t)&tsi_irq); + NVIC_EnableIRQ(TSI0_IRQn); + + selfCalibration(); +} + +static void initBaseline(TSIElectrode& elec) +{ + uint32_t channel0 = elec.getChannel(); + TSI0->DATA = ((channel0 << TSI_DATA_TSICH_SHIFT) ); + TSI0->DATA |= TSI_DATA_SWTS_MASK; + while(!(TSI0->GENCS & TSI_GENCS_EOSF_MASK)); + TSI0->GENCS |= TSI_GENCS_EOSF_MASK; + elec.setBaseline(TSI0->DATA & TSI_DATA_TSICNT_MASK); +} + +void TSIAnalogSlider::selfCalibration(void) +{ + TSI0->GENCS |= TSI_GENCS_EOSF_MASK; // Clear End of Scan Flag + TSI0->GENCS &= ~TSI_GENCS_TSIEN_MASK; // Disable TSI module + + uint32_t trigger_backup; + if(TSI0->GENCS & TSI_GENCS_STM_MASK) { // Back-up TSI Trigger mode from Application + trigger_backup = 1; + } else { + trigger_backup = 0; + } + + TSI0->GENCS &= ~TSI_GENCS_STM_MASK; // Use SW trigger + TSI0->GENCS &= ~TSI_GENCS_TSIIEN_MASK; // Enable TSI interrupts + TSI0->GENCS |= TSI_GENCS_TSIEN_MASK; // Enable TSI module + + initBaseline(_elec0); + initBaseline(_elec1); + + TSI0->DATA = ((_elec0.getChannel() << TSI_DATA_TSICH_SHIFT)); + + TSI0->GENCS &= ~TSI_GENCS_TSIEN_MASK; // Disable TSI module + TSI0->GENCS |= TSI_GENCS_TSIIEN_MASK; // Enale TSI interrupt + if (trigger_backup) { // Restore trigger mode + TSI0->GENCS |= TSI_GENCS_STM_MASK; + } else { + TSI0->GENCS &= ~TSI_GENCS_STM_MASK; + } + + TSI0->GENCS |= TSI_GENCS_TSIEN_MASK; // Enable TSI module + TSI0->DATA |= TSI_DATA_SWTS_MASK; +} + + +void TSIAnalogSlider::sliderRead(void ) { + if (_scan_in_progress) { + _scan_in_progress = 0; + uint32_t delta0 = _elec0.getDelta(); + uint32_t delta1 = _elec1.getDelta(); + + if ((delta0 > _elec0.getThreshold()) || (delta1 > _elec1.getThreshold())) { + uint32_t perc_pos0 = (delta0 * 100) / (delta0 + delta1); + uint32_t perc_pos1 = (delta1 * 100) / (delta0 + delta1); + setSliderPercPosition(0, perc_pos0); + setSliderPercPosition(1, perc_pos1); + uint32_t dist_pos0 = (perc_pos0 * _range) / 100; + uint32_t dist_pos1 = (perc_pos0 * _range) / 100; + setSliderDisPosition(0, dist_pos0); + setSliderDisPosition(1, dist_pos1); + + setAbsolutePosition(((100 - perc_pos0) + perc_pos1) / 2); + setAbsoluteDistance(((_range - dist_pos0) + dist_pos1) / 2); + } else { + setSliderPercPosition(0, 0); + setSliderPercPosition(1, 0); + setSliderDisPosition(0, 0); + setSliderDisPosition(1, 0); + setAbsolutePosition(0); + setAbsoluteDistance(0); + } + } +} + +float TSIAnalogSlider::readPercentage() { + sliderRead(); + return (float)getAbsolutePosition() / 100.0; +} + +uint32_t TSIAnalogSlider::readDistance() { + sliderRead(); + return getAbsoluteDistance(); +} + +static void changeElectrode(TSIAnalogSlider *analog_slider) +{ + TSIElectrode* elec = analog_slider->getCurrentElectrode(); + uint32_t signal = (TSI0->DATA & TSI_DATA_TSICNT_MASK); + elec->setSignal(signal); + + TSIElectrode *next_elec = analog_slider->getNextElectrode(elec); + + analog_slider->setCurrentElectrode(next_elec); + TSI0->DATA = ((next_elec->getChannel() << TSI_DATA_TSICH_SHIFT) ); + TSI0->DATA |= TSI_DATA_SWTS_MASK; +} + + +void tsi_irq(void) +{ + TSIAnalogSlider *analog_slider = TSIAnalogSlider::getInstance(); + analog_slider->setScan(1); + TSI0->GENCS |= TSI_GENCS_EOSF_MASK; // Clear End of Scan Flag + changeElectrode(analog_slider); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tsi_sensor.h Sat Feb 22 11:07:29 2014 +0000 @@ -0,0 +1,198 @@ +/* Freescale Semiconductor Inc. + * + * mbed Microcontroller Library + * (c) Copyright 2009-2012 ARM Limited. + * + * 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. + */ + +#ifndef TSISENSOR_H +#define TSISENSOR_H + +/** +* TSISensor example +* +* @code +* #include "mbed.h" +* #include "TSISensor.h" +* +* int main(void) { +* DigitalOut led(LED_GREEN); +* TSIElectrode elec0(9); +* TSIElectrode elec1(10); +* TSIAnalogSlider tsi(elec0, elec1, 40); +* +* while (true) { +* printf("slider percentage: %f%\r\n", tsi.readPercentage()); +* printf("slider distance: %dmm\r\n", tsi.readDistance()); +* wait(1); +* led = !led; +* } +* } +* @endcode +*/ +#define NO_TOUCH 0 + +/** TSI Electrode with simple data required for touch detection. + */ +class TSIElectrode { +public: + /** Initialize electrode. + */ + TSIElectrode(uint32_t tsi_channel) : _threshold(100) { + _channel = (uint8_t)tsi_channel; + } + /** Set baseline. + */ + void setBaseline(uint32_t baseline) { + _baseline = (uint16_t)baseline; + } + /** Set threshold. + */ + void setThreshold(uint32_t threshold) { + _threshold = (uint16_t)threshold; + } + /** Set signal. + */ + void setSignal(uint32_t signal) { + _signal = (uint16_t)signal; + } + /** Get baseline. + */ + uint32_t getBaseline() { + return _baseline; + } + /** Get delta. + */ + uint32_t getDelta() { + int32_t delta = getSignal() - getBaseline(); + if (delta < 0) { + return 0; + } else { + return delta; + } + } + /** Get signal. + */ + uint32_t getSignal() { + return _signal; + } + /** Get threshold. + */ + uint32_t getThreshold() { + return _threshold; + } + /** Get channel. + */ + uint32_t getChannel() { + return _channel; + } +private: + uint8_t _channel; + uint16_t _signal; + uint16_t _baseline; + uint16_t _threshold; +}; + +/** Analog slider which consists of two electrodes. + */ +class TSIAnalogSlider { +public: + /** + * Initialize the TSI Touch Sensor + */ + TSIAnalogSlider(TSIElectrode& elec0, TSIElectrode& elec1, uint32_t range); + /** + * Read Touch Sensor percentage value + * + * @returns percentage value between [0 ... 1] + */ + float readPercentage(); + /** + * Read Touch Sensor distance + * + * @returns distance in mm. The value is between [0 ... _range] + */ + uint32_t readDistance(); + /** Get current electrode. + */ + TSIElectrode* getCurrentElectrode() { + return _current_elec; + } + /** Set current electrode which is being measured. + */ + void setCurrentElectrode(TSIElectrode *elec){ + _current_elec = elec; + } + /** Get next electrode. + */ + TSIElectrode* getNextElectrode(TSIElectrode* electrode) { + if (electrode->getChannel() == _elec0.getChannel()) { + return &_elec1; + } else { + return &_elec0; + } + } + /** Return absolute distance position. + */ + uint32_t getAbsoluteDistance() { + return _absolute_distance_pos; + } + /** Return absolute precentage position. + */ + uint32_t getAbsolutePosition() { + return _absolute_percentage_pos; + } + /** Set value to the scan in progress flag. + */ + void setScan(uint32_t scan) { + _scan_in_progress = scan; + } + /** Return instance to Analog slider. Used in tsi irq. + */ + static TSIAnalogSlider *getInstance() { + return _instance; + } +private: + void sliderRead(void); + void selfCalibration(void); + void setSliderPercPosition(uint32_t elec_num, uint32_t position) { + _percentage_position[elec_num] = position; + } + void setSliderDisPosition(uint32_t elec_num, uint32_t position) { + _distance_position[elec_num] = position; + } + void setAbsolutePosition(uint32_t position) { + _absolute_percentage_pos = position; + } + void setAbsoluteDistance(uint32_t distance) { + _absolute_distance_pos = distance; + } +private: + TSIElectrode _elec0; + TSIElectrode _elec1; + uint8_t _scan_in_progress; + TSIElectrode* _current_elec; + uint8_t _percentage_position[2]; + uint8_t _distance_position[2]; + uint32_t _absolute_percentage_pos; + uint32_t _absolute_distance_pos; + uint8_t _range; +protected: + static TSIAnalogSlider *_instance; +}; + +#endif