capsense.c
Go to the documentation of this file.00001
00019
00020 #include "em_device.h"
00021
00022
00023 #include "em_emu.h"
00024 #include "em_acmp.h"
00025 #include "capsense.h"
00026
00030 static volatile uint8_t currentChannel;
00032 static volatile bool measurementComplete;
00033
00034
00038 static const bool channelsInUse[ACMP_CHANNELS] = CAPSENSE_CH_IN_USE;
00039
00040
00044 static volatile uint32_t channelValues[ACMP_CHANNELS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
00045
00046
00050 static volatile uint32_t channelMaxValues[ACMP_CHANNELS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
00051
00054
00061 void TIMER0_IRQHandler(void)
00062 {
00063 uint32_t count;
00064
00065
00066 TIMER0->CMD = TIMER_CMD_STOP;
00067 TIMER1->CMD = TIMER_CMD_STOP;
00068
00069
00070 TIMER0->IFC = TIMER_IFC_OF;
00071
00072
00073 count = TIMER1->CNT;
00074
00075
00076 channelValues[currentChannel] = count;
00077
00078
00079 if (count > channelMaxValues[currentChannel])
00080 channelMaxValues[currentChannel] = count;
00081
00082 measurementComplete = true;
00083 }
00084
00085
00090 uint32_t CAPSENSE_getVal(uint8_t channel)
00091 {
00092 return channelValues[channel];
00093 }
00094
00095
00100 uint32_t CAPSENSE_getNormalizedVal(uint8_t channel)
00101 {
00102 uint32_t max = channelMaxValues[channel];
00103 return (channelValues[channel] << 8) / max;
00104 }
00105
00106
00112 bool CAPSENSE_getPressed(uint8_t channel)
00113 {
00114 uint32_t treshold;
00115
00116
00117
00118 treshold = channelMaxValues[channel];
00119 treshold -= channelMaxValues[channel] >> 3;
00120
00121 if (channelValues[channel] < treshold)
00122 {
00123 return true;
00124 }
00125 return false;
00126 }
00127
00128
00133 int32_t CAPSENSE_getSliderPosition(void)
00134 {
00135 int i;
00136 int minPos = -1;
00137 uint32_t minVal = 224;
00138
00139
00140
00141 uint32_t interpol[6] = { 255, 255, 255, 255, 255, 255 };
00142
00143
00144 int position;
00145
00146
00147
00148
00149
00150
00151 for (i = 1; i < 5; i++)
00152 {
00153
00154 interpol[i] = channelValues[i - 1] << 8;
00155 interpol[i] /= channelMaxValues[i - 1];
00156
00157 if (interpol[i] < minVal)
00158 {
00159 minVal = interpol[i];
00160 minPos = i;
00161 }
00162 }
00163
00164 if (minPos == -1)
00165 return -1;
00166
00167
00168
00169 position = (minPos - 1) << 4;
00170
00171
00172 position -= ((256 - interpol[minPos - 1]) << 3)
00173 / (256 - interpol[minPos]);
00174
00175
00176 position += ((256 - interpol[minPos + 1]) << 3)
00177 / (256 - interpol[minPos]);
00178
00179 return position;
00180 }
00181
00182
00187 void CAPSENSE_Sense(void)
00188 {
00189
00190 ACMP_Enable(ACMP_CAPSENSE);
00191
00192 uint8_t ch;
00193
00194 for (currentChannel = 0; currentChannel < ACMP_CHANNELS; currentChannel++)
00195 {
00196
00197 if (!channelsInUse[currentChannel])
00198 {
00199 continue;
00200 }
00201
00202
00203 ch = currentChannel;
00204 ACMP_CapsenseChannelSet(ACMP_CAPSENSE, (ACMP_Channel_TypeDef) ch);
00205
00206
00207 TIMER0->CNT = 0;
00208 TIMER1->CNT = 0;
00209
00210 measurementComplete = false;
00211
00212
00213 TIMER0->CMD = TIMER_CMD_START;
00214 TIMER1->CMD = TIMER_CMD_START;
00215
00216
00217 while ( measurementComplete == false )
00218 {
00219 EMU_EnterEM1();
00220 }
00221 }
00222
00223
00224 ACMP_Disable(ACMP_CAPSENSE);
00225 }
00226
00227
00235 void CAPSENSE_Init(void)
00236 {
00237
00238 ACMP_CapsenseInit_TypeDef capsenseInit = ACMP_CAPSENSE_INIT_DEFAULT;
00239
00240
00241 CMU->HFPERCLKDIV |= CMU_HFPERCLKDIV_HFPERCLKEN;
00242 CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_TIMER0
00243 | CMU_HFPERCLKEN0_TIMER1
00244 | ACMP_CAPSENSE_CLKEN
00245 | CMU_HFPERCLKEN0_PRS;
00246
00247
00248 TIMER0->CTRL = TIMER_CTRL_PRESC_DIV512;
00249 TIMER0->TOP = 10;
00250 TIMER0->IEN = TIMER_IEN_OF;
00251 TIMER0->CNT = 0;
00252
00253
00254 TIMER1->CTRL = TIMER_CTRL_PRESC_DIV1024 | TIMER_CTRL_CLKSEL_CC1;
00255 TIMER1->TOP = 0xFFFF;
00256
00257
00258 TIMER1->CC[1].CTRL = TIMER_CC_CTRL_MODE_INPUTCAPTURE
00259 | TIMER_CC_CTRL_PRSSEL_PRSCH0
00260 | TIMER_CC_CTRL_INSEL_PRS
00261 | TIMER_CC_CTRL_ICEVCTRL_RISING
00262 | TIMER_CC_CTRL_ICEDGE_BOTH;
00263
00264
00265 PRS->CH[0].CTRL = PRS_CH_CTRL_EDSEL_POSEDGE
00266 | PRS_CH_CTRL_SOURCESEL_ACMP_CAPSENSE
00267 | PRS_CH_CTRL_SIGSEL_ACMPOUT_CAMPSENSE;
00268
00269
00270 ACMP_CapsenseInit(ACMP_CAPSENSE, &capsenseInit);
00271
00272
00273 NVIC_EnableIRQ(TIMER0_IRQn);
00274 }