00001
00019
00020 #include "em_device.h"
00021
00022
00023 #include "caplesense.h"
00024 #include "em_emu.h"
00025 #include "em_acmp.h"
00026 #include "em_assert.h"
00027 #include "em_cmu.h"
00028 #include "em_emu.h"
00029 #include "em_gpio.h"
00030 #include "em_int.h"
00031 #include "em_lesense.h"
00032
00033
00034 #include "caplesenseconfig.h"
00035
00036
00040 static volatile uint32_t channelValues[LESENSE_CHANNELS] =
00041 {
00042
00043 0, 0, 0, 0, 0, 0, 0, 0,
00044
00045 0, 0, 0, 0, 0, 0, 0, 0
00046 };
00047
00048
00049
00053 static volatile uint32_t channelMaxValues[LESENSE_CHANNELS] =
00054 {
00055
00056 1, 1, 1, 1, 1, 1, 1, 1,
00057
00058 1, 1, 1, 1, 1, 1, 1, 1
00059 };
00060
00061
00065 static const bool channelsInUse[LESENSE_CHANNELS] = LESENSE_CAPSENSE_CH_IN_USE;
00066
00067
00070 void CAPLESENSE_setupCMU(void);
00071 void CAPLESENSE_setupGPIO(void);
00072 void CAPLESENSE_setupACMP(void);
00073
00074
00075
00079 static void (*lesenseScanCb)(void);
00081 static void (*lesenseChCb)(void);
00082
00084 static volatile uint8_t currentChannel;
00085
00086
00087
00088
00091 void CAPLESENSE_setupCMU(void)
00092 {
00093
00094 SystemCoreClockUpdate();
00095
00096
00097 CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFRCO);
00098
00099 CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO);
00100
00101 CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_Disabled);
00102
00103
00104 CMU_ClockEnable(cmuClock_HFPER, 1);
00105
00106 CMU_ClockEnable(cmuClock_GPIO, 1);
00107
00108 CMU_ClockEnable(cmuClock_ACMP0, 1);
00109
00110 CMU_ClockEnable(cmuClock_ACMP1, 1);
00111
00112 CMU_ClockEnable(cmuClock_CORELE, 1);
00113
00114 CMU_ClockEnable(cmuClock_LESENSE, 1);
00115
00116
00117 CMU_ClockDivSet(cmuClock_LESENSE, cmuClkDiv_1);
00118 }
00119
00120
00121
00124 void CAPLESENSE_setupGPIO(void)
00125 {
00126
00127 GPIO_DriveModeSet(CAPLESENSE_SLIDER_PORT0, gpioDriveModeStandard);
00128
00129
00130
00131 GPIO_PinModeSet(CAPLESENSE_SLIDER_PORT0, CAPLESENSE_SLIDER0_PIN, gpioModeDisabled, 0);
00132 GPIO_PinModeSet(CAPLESENSE_SLIDER_PORT0, CAPLESENSE_SLIDER1_PIN, gpioModeDisabled, 0);
00133 GPIO_PinModeSet(CAPLESENSE_SLIDER_PORT0, CAPLESENSE_SLIDER2_PIN, gpioModeDisabled, 0);
00134 GPIO_PinModeSet(CAPLESENSE_SLIDER_PORT0, CAPLESENSE_SLIDER3_PIN, gpioModeDisabled, 0);
00135 }
00136
00137
00138
00141 void CAPLESENSE_setupACMP(void)
00142 {
00143
00144 static const ACMP_CapsenseInit_TypeDef initACMP =
00145 {
00146 .fullBias = false,
00147 .halfBias = false,
00148 .biasProg = 0x7,
00149 .warmTime = acmpWarmTime512,
00150 .hysteresisLevel = acmpHysteresisLevel7,
00151 .resistor = acmpResistor0,
00152 .lowPowerReferenceEnabled = false,
00153 .vddLevel = 0x3D,
00154 .enable = false
00155 };
00156
00157
00158
00159 ACMP_GPIOSetup(ACMP0, 0, false, false);
00160 ACMP_GPIOSetup(ACMP1, 0, false, false);
00161
00162
00163 ACMP_CapsenseInit(ACMP0, &initACMP);
00164 ACMP_CapsenseInit(ACMP1, &initACMP);
00165
00166
00167 }
00168
00169
00170
00174 void CAPLESENSE_setupLESENSE(bool sleep)
00175 {
00176 uint8_t i;
00177 static bool init = true;
00178
00179
00180 static uint16_t capsenseCalibrateVals[4];
00181
00182
00183 static const LESENSE_ChAll_TypeDef initChsSense = LESENSE_CAPSENSE_SCAN_CONF_SENSE;
00184
00185 static const LESENSE_ChAll_TypeDef initChsSleep = LESENSE_CAPSENSE_SCAN_CONF_SLEEP;
00186
00187 static const LESENSE_Init_TypeDef initLESENSE =
00188 {
00189 .coreCtrl =
00190 {
00191 .scanStart = lesenseScanStartPeriodic,
00192 .prsSel = lesensePRSCh0,
00193 .scanConfSel = lesenseScanConfDirMap,
00194 .invACMP0 = false,
00195 .invACMP1 = false,
00196 .dualSample = false,
00197 .storeScanRes = false,
00198 .bufOverWr = true,
00199 .bufTrigLevel = lesenseBufTrigHalf,
00200 .wakeupOnDMA = lesenseDMAWakeUpDisable,
00201 .biasMode = lesenseBiasModeDutyCycle,
00202 .debugRun = false
00203 },
00204
00205 .timeCtrl =
00206 {
00207 .startDelay = 0U
00208 },
00209
00210 .perCtrl =
00211 {
00212 .dacCh0Data = lesenseDACIfData,
00213 .dacCh0ConvMode = lesenseDACConvModeDisable,
00214 .dacCh0OutMode = lesenseDACOutModeDisable,
00215 .dacCh1Data = lesenseDACIfData,
00216 .dacCh1ConvMode = lesenseDACConvModeDisable,
00217 .dacCh1OutMode = lesenseDACOutModeDisable,
00218 .dacPresc = 0U,
00219 .dacRef = lesenseDACRefBandGap,
00220 .acmp0Mode = lesenseACMPModeMuxThres,
00221 .acmp1Mode = lesenseACMPModeMuxThres,
00222 .warmupMode = lesenseWarmupModeNormal
00223 },
00224
00225 .decCtrl =
00226 {
00227 .decInput = lesenseDecInputSensorSt,
00228 .chkState = false,
00229 .intMap = true,
00230 .hystPRS0 = false,
00231 .hystPRS1 = false,
00232 .hystPRS2 = false,
00233 .hystIRQ = false,
00234 .prsCount = true,
00235 .prsChSel0 = lesensePRSCh0,
00236 .prsChSel1 = lesensePRSCh1,
00237 .prsChSel2 = lesensePRSCh2,
00238 .prsChSel3 = lesensePRSCh3
00239 }
00240 };
00241
00242
00243 if (init)
00244 {
00245
00246 LESENSE_Init(&initLESENSE, true);
00247 }
00248
00249
00250 if (sleep)
00251 {
00252
00253 LESENSE_ScanStop();
00254
00255
00256 while (LESENSE_STATUS_SCANACTIVE & LESENSE_StatusGet()) ;
00257
00258
00259 LESENSE_ResultBufferClear();
00260
00261
00262 (void) LESENSE_ScanFreqSet(0U, 4U);
00263
00264
00265 LESENSE_ClkDivSet(lesenseClkLF, lesenseClkDiv_1);
00266
00267
00268 LESENSE_ChannelAllConfig(&initChsSleep);
00269
00270
00271 LESENSE_ChannelThresSet(CAPLESENSE_SLIDER0_PIN, CAPLESENSE_ACMP_VDD_SCALE, capsenseCalibrateVals[0]);
00272 LESENSE_ChannelThresSet(CAPLESENSE_SLIDER1_PIN, CAPLESENSE_ACMP_VDD_SCALE, capsenseCalibrateVals[1]);
00273 LESENSE_ChannelThresSet(CAPLESENSE_SLIDER2_PIN, CAPLESENSE_ACMP_VDD_SCALE, capsenseCalibrateVals[2]);
00274 LESENSE_ChannelThresSet(CAPLESENSE_SLIDER3_PIN, CAPLESENSE_ACMP_VDD_SCALE, capsenseCalibrateVals[3]);
00275
00276
00277 LESENSE_IntDisable(LESENSE_IEN_SCANCOMPLETE);
00278 }
00279 else
00280 {
00281
00282 LESENSE_ScanStop();
00283
00284
00285 while (LESENSE_STATUS_SCANACTIVE & LESENSE_StatusGet()) ;
00286
00287
00288 LESENSE_IntClear(LESENSE_IEN_SCANCOMPLETE);
00289
00290
00291 LESENSE_ResultBufferClear();
00292
00293
00294 (void) LESENSE_ScanFreqSet(0U, 64U);
00295
00296
00297 LESENSE_ClkDivSet(lesenseClkLF, lesenseClkDiv_8);
00298
00299
00300 LESENSE_ChannelAllConfig(&initChsSense);
00301
00302
00303 LESENSE_IntEnable(LESENSE_IEN_SCANCOMPLETE);
00304 }
00305
00306
00307 NVIC_EnableIRQ(LESENSE_IRQn);
00308
00309
00310 LESENSE_ScanStart();
00311
00312
00313 if (init)
00314 {
00315
00316
00317 init = false;
00318
00319
00320 while (!(LESENSE->STATUS & LESENSE_STATUS_BUFHALFFULL)) ;
00321
00322
00323 for (i = 0U; i < CAPLESENSE_NUMOF_SLIDERS; i++)
00324 {
00325 capsenseCalibrateVals[i] = LESENSE_ScanResultDataBufferGet(i) - CAPLESENSE_SENSITIVITY_OFFS;
00326 }
00327
00328
00329 LESENSE_ChannelThresSet(CAPLESENSE_SLIDER0_PIN, CAPLESENSE_ACMP_VDD_SCALE, capsenseCalibrateVals[0]);
00330 LESENSE_ChannelThresSet(CAPLESENSE_SLIDER1_PIN, CAPLESENSE_ACMP_VDD_SCALE, capsenseCalibrateVals[1]);
00331 LESENSE_ChannelThresSet(CAPLESENSE_SLIDER2_PIN, CAPLESENSE_ACMP_VDD_SCALE, capsenseCalibrateVals[2]);
00332 LESENSE_ChannelThresSet(CAPLESENSE_SLIDER3_PIN, CAPLESENSE_ACMP_VDD_SCALE, capsenseCalibrateVals[3]);
00333 }
00334 }
00335
00336
00337
00342 void CAPLESENSE_setupCallbacks(void (*scanCb)(void), void (*chCb)(void))
00343 {
00344 lesenseScanCb = scanCb;
00345 lesenseChCb = chCb;
00346 }
00347
00348
00349
00352 void LESENSE_IRQHandler(void)
00353 {
00354 uint32_t count;
00355
00356
00357
00358 if (LESENSE_IF_SCANCOMPLETE & LESENSE_IntGetEnabled())
00359 {
00360 LESENSE_IntClear(LESENSE_IF_SCANCOMPLETE);
00361
00362
00363 for (currentChannel = 0; currentChannel < LESENSE_CHANNELS; currentChannel++)
00364 {
00365
00366 if (!channelsInUse[currentChannel])
00367 {
00368 continue;
00369 }
00370
00371
00372 count = LESENSE_ScanResultDataGet();
00373
00374
00375 channelValues[currentChannel] = count;
00376
00377
00378 if (count > channelMaxValues[currentChannel])
00379 {
00380 channelMaxValues[currentChannel] = count;
00381 }
00382 }
00383
00384
00385 if (lesenseScanCb != 0x00000000)
00386 {
00387 lesenseScanCb();
00388 }
00389 }
00390
00391
00392 if (CAPLESENSE_CHANNEL_INT & LESENSE_IntGetEnabled())
00393 {
00394
00395 LESENSE_IntClear(CAPLESENSE_CHANNEL_INT);
00396
00397
00398 if (lesenseChCb != 0x00000000)
00399 {
00400 lesenseChCb();
00401 }
00402 }
00403 }
00404
00405
00406
00411 uint8_t CAPLESENSE_getSegmentChannel(uint8_t capSegment)
00412 {
00413 uint8_t channel;
00414
00415 switch (capSegment)
00416 {
00417 case(0):
00418 channel = SLIDER_PART0_CHANNEL;
00419 break;
00420 case(1):
00421 channel = SLIDER_PART1_CHANNEL;
00422 break;
00423 case(2):
00424 channel = SLIDER_PART2_CHANNEL;
00425 break;
00426 default:
00427 channel = SLIDER_PART3_CHANNEL;
00428 break;
00429 }
00430 return channel;
00431
00432 }
00433
00434
00435
00440 uint32_t CAPLESENSE_getVal(uint8_t channel)
00441 {
00442 return channelValues[channel];
00443 }
00444
00445
00450 uint32_t CAPLESENSE_getNormalizedVal(uint8_t channel)
00451 {
00452 uint32_t max = channelMaxValues[channel];
00453 return (channelValues[channel] << 8) / max;
00454 }
00455
00456
00457
00458
00463 int32_t CAPLESENSE_getSliderPosition(void)
00464 {
00465 int i;
00466 int minPos = -1;
00467 uint32_t minVal = 236;
00468
00469
00470
00471 uint32_t interpol[6] = { 255, 255, 255, 255, 255, 255 };
00472 uint32_t channelPattern[] = { 0, SLIDER_PART0_CHANNEL + 1,
00473 SLIDER_PART1_CHANNEL + 1,
00474 SLIDER_PART2_CHANNEL + 1,
00475 SLIDER_PART3_CHANNEL + 1 };
00476
00477
00478 int position;
00479
00480
00481
00482
00483
00484
00485 for (i = 1; i < CAPLESENSE_NUMOF_SLIDERS + 1; i++)
00486 {
00487
00488 interpol[i] = channelValues[channelPattern[i] - 1] << 8;
00489 interpol[i] /= channelMaxValues[channelPattern[i] - 1];
00490
00491 if (interpol[i] < minVal)
00492 {
00493 minVal = interpol[i];
00494 minPos = i;
00495 }
00496 }
00497
00498 if (minPos == -1)
00499 return -1;
00500
00501
00502
00503 position = (minPos - 1) << 4;
00504
00505
00506 position -= ((256 - interpol[minPos - 1]) << 3)
00507 / (256 - interpol[minPos]);
00508
00509
00510 position += ((256 - interpol[minPos + 1]) << 3)
00511 / (256 - interpol[minPos]);
00512
00513 return position;
00514 }
00515
00516
00517
00520 void CAPLESENSE_Sleep(void)
00521 {
00522
00523 EMU_EnterEM2(true);
00524 }
00525
00526
00527
00531 void CAPLESENSE_Init(bool sleep)
00532 {
00533
00534 INT_Disable();
00535
00536
00537 CAPLESENSE_setupCMU();
00538
00539 CAPLESENSE_setupGPIO();
00540
00541 CAPLESENSE_setupACMP();
00542
00543 CAPLESENSE_setupLESENSE(sleep);
00544
00545
00546 INT_Enable();
00547 }
00548
00549