172 lines
3.7 KiB
C
172 lines
3.7 KiB
C
/*
|
|
* @file wave_analyzer_hw.c
|
|
* @brief Helper methods related to Input Capture Unit (ICU)
|
|
*
|
|
* @date Jun 23, 2013
|
|
* @author Andrey Belomutskiy, (c) 2012-2014
|
|
*/
|
|
|
|
#include "wave_analyzer_hw.h"
|
|
#include "eficonsole.h"
|
|
#include "pin_repository.h"
|
|
|
|
static void icuWidthCallback(ICUDriver *driver);
|
|
static void icuPeriordCallBack(ICUDriver *driver);
|
|
|
|
/*
|
|
* 30ms seems like width maximum, at 16bit precision that means
|
|
* CORE_CLOCK / 33.33333 = TICKS * 65536
|
|
* 168000000 / 33.333333 / 65536 = 76.90
|
|
*/
|
|
static ICUConfig wave_icucfg = { ICU_INPUT_ACTIVE_LOW, CORE_CLOCK / 100, icuWidthCallback, icuPeriordCallBack, 0,
|
|
ICU_CHANNEL_1, 0 };
|
|
|
|
static int registeredIcuCount = 0;
|
|
static WaveReaderHw* registeredIcus[8];
|
|
|
|
static WaveReaderHw * findWaveReaderHw(ICUDriver *driver) {
|
|
for (int i = 0; i < registeredIcuCount; i++) {
|
|
if (registeredIcus[i]->driver == driver) {
|
|
return registeredIcus[i];
|
|
}
|
|
}
|
|
firmwareError("reader not found");
|
|
return (WaveReaderHw *) NULL;
|
|
}
|
|
|
|
static void icuWidthCallback(ICUDriver *driver) {
|
|
/*
|
|
* see comment in icuPeriordCallBack
|
|
int rowWidth = icuGetWidth(driver);
|
|
*/
|
|
WaveReaderHw * hw = findWaveReaderHw(driver);
|
|
invokeJustArgCallbacks(&hw->widthListeners);
|
|
}
|
|
|
|
static void icuPeriordCallBack(ICUDriver *driver) {
|
|
/*
|
|
* we do not use timer period at all - we just need the event. For all time characteristics,
|
|
* we use system time
|
|
* int period = icuGetPeriod(driver);
|
|
*/
|
|
|
|
WaveReaderHw * hw = findWaveReaderHw(driver);
|
|
invokeJustArgCallbacks(&hw->periodListeners);
|
|
}
|
|
|
|
static uint32_t getAlternateFunctions(ICUDriver *driver) {
|
|
if (driver == NULL) {
|
|
firmwareError("getAlternateFunctions(NULL)");
|
|
return 0xffffffff;
|
|
}
|
|
#if STM32_ICU_USE_TIM1
|
|
if (driver == &ICUD1) {
|
|
return GPIO_AF_TIM1;
|
|
}
|
|
#endif
|
|
#if STM32_ICU_USE_TIM2
|
|
if (driver == &ICUD2) {
|
|
return GPIO_AF_TIM2;
|
|
}
|
|
#endif
|
|
#if STM32_ICU_USE_TIM3
|
|
if (driver == &ICUD3) {
|
|
return GPIO_AF_TIM3;
|
|
}
|
|
#endif
|
|
#if STM32_ICU_USE_TIM4
|
|
if (driver == &ICUD4) {
|
|
return GPIO_AF_TIM4;
|
|
}
|
|
#endif
|
|
#if STM32_ICU_USE_TIM9
|
|
if (driver == &ICUD9) {
|
|
return GPIO_AF_TIM9;
|
|
}
|
|
#endif
|
|
firmwareError("No such driver");
|
|
return 0xffffffff;
|
|
}
|
|
|
|
icuchannel_t getInputCaptureChannel(brain_pin_e hwPin) {
|
|
switch (hwPin) {
|
|
case GPIOA_5:
|
|
case GPIOA_8:
|
|
case GPIOC_6:
|
|
case GPIOE_5:
|
|
case GPIOE_9:
|
|
return ICU_CHANNEL_1;
|
|
|
|
case GPIOE_6:
|
|
case GPIOE_11:
|
|
return ICU_CHANNEL_2;
|
|
default:
|
|
firmwareError("Unexpected hw pin in getInputCaptureChannel %d", hwPin);
|
|
return ICU_CHANNEL_1;
|
|
}
|
|
}
|
|
|
|
ICUDriver * getInputCaptureDriver(brain_pin_e hwPin) {
|
|
#if STM32_ICU_USE_TIM1
|
|
if (hwPin == GPIOA_8) {
|
|
return &ICUD1;
|
|
}
|
|
if (hwPin == GPIOE_9) {
|
|
return &ICUD1;
|
|
}
|
|
if (hwPin == GPIOE_11) {
|
|
return &ICUD1;
|
|
}
|
|
#endif
|
|
#if STM32_ICU_USE_TIM2
|
|
if (hwPin == GPIOA_5) {
|
|
return &ICUD2;
|
|
}
|
|
#endif
|
|
#if STM32_ICU_USE_TIM3
|
|
if (hwPin == GPIOC_6) {
|
|
return &ICUD3;
|
|
}
|
|
#endif
|
|
#if STM32_ICU_USE_TIM9
|
|
if (hwPin == GPIOE_5) {
|
|
return &ICUD9;
|
|
}
|
|
#endif
|
|
return (ICUDriver *) NULL;
|
|
}
|
|
|
|
void initWaveAnalyzerDriver(WaveReaderHw *hw, ICUDriver *driver, ioportid_t port, ioportmask_t pin) {
|
|
hw->driver = driver;
|
|
hw->port = port;
|
|
hw->pin = pin;
|
|
if (driver != NULL) {
|
|
iomode_t mode = (iomode_t) PAL_MODE_ALTERNATE(getAlternateFunctions(driver));
|
|
mySetPadMode("wave input", port, pin, mode);
|
|
|
|
// hw->widthListeners.currentListenersCount = 0;
|
|
|
|
registeredIcus[registeredIcuCount++] = hw;
|
|
}
|
|
}
|
|
|
|
void setWaveReaderMode(WaveReaderHw *hw, bool mode) {
|
|
hw->activeMode = mode;
|
|
if (hw->activeMode) {
|
|
wave_icucfg.mode = ICU_INPUT_ACTIVE_HIGH;
|
|
} else {
|
|
wave_icucfg.mode = ICU_INPUT_ACTIVE_LOW;
|
|
}
|
|
ICUDriver *driver = hw->driver;
|
|
|
|
if (driver != NULL) {
|
|
if (hw->started) {
|
|
icuDisable(driver);
|
|
icuStop(driver);
|
|
}
|
|
icuStart(driver, &wave_icucfg);
|
|
icuEnable(driver);
|
|
}
|
|
hw->started = TRUE;
|
|
}
|