capsense.c
Go to the documentation of this file.00001
00036
00037 #include "em_device.h"
00038
00039
00040 #include "capsense.h"
00041 #include "em_emu.h"
00042 #include "em_acmp.h"
00043 #include "capsenseconfig.h"
00044
00046 static volatile uint8_t currentChannel;
00047
00048
00052 static const bool channelsInUse[ACMP_CHANNELS] = CAPSENSE_CH_IN_USE;
00053
00054
00058 static volatile uint32_t channelValues[ACMP_CHANNELS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
00059
00060
00064 static volatile uint32_t channelMaxValues[ACMP_CHANNELS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
00065
00066
00067
00074 void TIMER0_IRQHandler(void)
00075 {
00076 uint32_t count;
00077
00078
00079 TIMER0->CMD = TIMER_CMD_STOP;
00080 TIMER1->CMD = TIMER_CMD_STOP;
00081
00082
00083 TIMER0->IFC = TIMER_IFC_OF;
00084
00085
00086 count = TIMER1->CNT;
00087
00088
00089 channelValues[currentChannel] = count;
00090
00091
00092 if (count > channelMaxValues[currentChannel])
00093 channelMaxValues[currentChannel] = count;
00094 }
00095
00096
00101 uint32_t CAPSENSE_getVal(uint8_t channel)
00102 {
00103 return channelValues[channel];
00104 }
00105
00106
00111 uint8_t CAPSENSE_getSegmentChannel(uint8_t capSegment)
00112 {
00113 uint8_t channel;
00114
00115 switch (capSegment)
00116 {
00117 case(0):
00118 channel = SLIDER_PART0_CHANNEL;
00119 break;
00120 case(1):
00121 channel = SLIDER_PART1_CHANNEL;
00122 break;
00123 case(2):
00124 channel = SLIDER_PART2_CHANNEL;
00125 break;
00126 default:
00127 channel = SLIDER_PART3_CHANNEL;
00128 break;
00129 }
00130 return channel;
00131
00132 }
00133
00134
00138 uint8_t CAPSENSE_getButtonChannel(void)
00139 {
00140 uint8_t channel = BUTTON_CHANNEL;
00141 return channel;
00142
00143 }
00144
00145
00150 uint32_t CAPSENSE_getNormalizedVal(uint8_t channel)
00151 {
00152 uint32_t max = channelMaxValues[channel];
00153 return (channelValues[channel] << 8) / max;
00154 }
00155
00156
00162 bool CAPSENSE_getPressed(uint8_t channel)
00163 {
00164 uint32_t treshold;
00165
00166
00167
00168 treshold = channelMaxValues[channel];
00169 treshold -= channelMaxValues[channel] >> 3;
00170
00171 if (channelValues[channel] < treshold)
00172 {
00173 return true;
00174 }
00175 return false;
00176 }
00177
00178
00183 int32_t CAPSENSE_getSliderPosition(void)
00184 {
00185 int i;
00186 int minPos = -1;
00187 uint32_t minVal = 224;
00188
00189
00190
00191 uint32_t interpol[6] = { 255, 255, 255, 255, 255, 255 };
00192
00193
00194 int position;
00195
00196
00197
00198
00199
00200
00201 for (i = 1; i < 5; i++)
00202 {
00203
00204 interpol[i] = channelValues[i - 1] << 8;
00205 interpol[i] /= channelMaxValues[i - 1];
00206
00207 if (interpol[i] < minVal)
00208 {
00209 minVal = interpol[i];
00210 minPos = i;
00211 }
00212 }
00213
00214 if (minPos == -1)
00215 return -1;
00216
00217
00218
00219 position = (minPos - 1) << 4;
00220
00221
00222 position -= ((256 - interpol[minPos - 1]) << 3)
00223 / (256 - interpol[minPos]);
00224
00225
00226 position += ((256 - interpol[minPos + 1]) << 3)
00227 / (256 - interpol[minPos]);
00228
00229 return position;
00230 }
00231
00232
00237 void CAPSENSE_Sense(void)
00238 {
00239
00240 ACMP_Enable(ACMP_CAPSENSE);
00241
00242 uint8_t ch;
00243
00244 for (currentChannel = 0; currentChannel < ACMP_CHANNELS; currentChannel++)
00245 {
00246
00247 if (!channelsInUse[currentChannel])
00248 {
00249 continue;
00250 }
00251
00252
00253 ch = currentChannel;
00254 ACMP_CapsenseChannelSet(ACMP_CAPSENSE, (ACMP_Channel_TypeDef) ch);
00255
00256
00257 TIMER0->CNT = 0;
00258 TIMER1->CNT = 0;
00259
00260
00261 TIMER0->CMD = TIMER_CMD_START;
00262 TIMER1->CMD = TIMER_CMD_START;
00263
00264
00265 EMU_EnterEM1();
00266 }
00267
00268
00269 ACMP_Disable(ACMP_CAPSENSE);
00270 }
00271
00272
00280 void CAPSENSE_Init(void)
00281 {
00282
00283 ACMP_CapsenseInit_TypeDef capsenseInit = ACMP_CAPSENSE_INIT_DEFAULT;
00284
00285
00286 CMU->HFPERCLKDIV |= CMU_HFPERCLKDIV_HFPERCLKEN;
00287 CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_TIMER0
00288 | CMU_HFPERCLKEN0_TIMER1
00289 | ACMP_CAPSENSE_CLKEN
00290 | CMU_HFPERCLKEN0_PRS;
00291
00292
00293 TIMER0->CTRL = TIMER_CTRL_PRESC_DIV512;
00294 TIMER0->TOP = 10;
00295 TIMER0->IEN = TIMER_IEN_OF;
00296 TIMER0->CNT = 0;
00297
00298
00299 TIMER1->CTRL = TIMER_CTRL_PRESC_DIV1024 | TIMER_CTRL_CLKSEL_CC1;
00300 TIMER1->TOP = 0xFFFF;
00301
00302
00303 TIMER1->CC[1].CTRL = TIMER_CC_CTRL_MODE_INPUTCAPTURE
00304 | TIMER_CC_CTRL_PRSSEL_PRSCH0
00305 | TIMER_CC_CTRL_INSEL_PRS
00306 | TIMER_CC_CTRL_ICEVCTRL_RISING
00307 | TIMER_CC_CTRL_ICEDGE_BOTH;
00308
00309
00310 PRS->CH[0].CTRL = PRS_CH_CTRL_EDSEL_POSEDGE
00311 | PRS_CH_CTRL_SOURCESEL_ACMP_CAPSENSE
00312 | PRS_CH_CTRL_SIGSEL_ACMPOUT_CAMPSENSE;
00313
00314
00315 ACMP_CapsenseInit(ACMP_CAPSENSE, &capsenseInit);
00316
00317
00318 NVIC_EnableIRQ(TIMER0_IRQn);
00319 }