f468e09499
git-svn-id: file:///srv/dev-disk-by-uuid-17e88007-4d0c-45e0-8757-cacfcc458630/repositories/svn/Diplomarbeit@131 9fe90eed-be63-e94b-8204-d34ff4c2ff93
719 lines
22 KiB
C
719 lines
22 KiB
C
/* ---------------------------------------------------------------------------
|
|
* dio.c - v0.1 (c) 2007 Micro-key bv
|
|
* ---------------------------------------------------------------------------
|
|
* Micro-key bv
|
|
* Industrieweg 28, 9804 TG Noordhorn
|
|
* Postbus 92, 9800 AB Zuidhorn
|
|
* The Netherlands
|
|
* Tel: +31 594 503020
|
|
* Fax: +31 594 505825
|
|
* Email: support@microkey.nl
|
|
* Web: www.microkey.nl
|
|
* ---------------------------------------------------------------------------
|
|
* Description: Digital inputs/outputs interface.
|
|
* ---------------------------------------------------------------------------
|
|
* Version(s): 0.1, 28-11-2007, fvds.
|
|
* Creation.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* System include files
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
/* Compiler includes */
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
/* Hardware Includes */
|
|
#include "LPC23xx.h"
|
|
#include "types.h"
|
|
|
|
/* FreeRTOS includes */
|
|
#include "FreeRTOS.h"
|
|
#include "Task.h"
|
|
#include "queue.h"
|
|
/* ---------------------------------------------------------------------------
|
|
* Application include files
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
#include "dio.h"
|
|
#include "dioISR.h"
|
|
#include "armVIC.h"
|
|
#include "ElecStatusCache.h"
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Local constant and macro definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
#define PORT0_BASE_ADDR FIO_BASE_ADDR
|
|
#define PORT1_BASE_ADDR (FIO_BASE_ADDR + 0x20)
|
|
#define PORT2_BASE_ADDR (FIO_BASE_ADDR + 0x40)
|
|
#define PORT3_BASE_ADDR (FIO_BASE_ADDR + 0x60)
|
|
#define PORT4_BASE_ADDR (FIO_BASE_ADDR + 0x80)
|
|
|
|
#define DIR_OFFSET (0x00)
|
|
#define MASK_OFFSET (0x10)
|
|
#define PIN_OFFSET (0x14)
|
|
#define SET_OFFSET (0x18)
|
|
#define CLR_OFFSET (0x1C)
|
|
|
|
// \MARK NEW PINSETTINGS FOR TESTER (2)
|
|
#if (PINSET_TESTER == 2)
|
|
#define DIO_MUX_DIR FIO3DIR
|
|
#define DIO_MUX_SET FIO3SET
|
|
#define DIO_MUX_CLR FIO3CLR
|
|
|
|
#define DIN_MUX_BIT BIT(25)
|
|
#define DIN_MUX_SET (DIO_MUX_SET = DIN_MUX_BIT)
|
|
#define DIN_MUX_CLR (DIO_MUX_CLR = DIN_MUX_BIT)
|
|
|
|
|
|
#define DOUT_MUX_BIT BIT(26)
|
|
#define DOUT_MUX_SET (DIO_MUX_SET = DOUT_MUX_BIT)
|
|
#define DOUT_MUX_CLR (DIO_MUX_CLR = DOUT_MUX_BIT)
|
|
#endif
|
|
|
|
#define DISPATCH_TASK_PRIO (tskIDLE_PRIORITY + 5)
|
|
#define DISPATCH_QUEUE_SIZE 10
|
|
|
|
#define Int_queue_time 3 /* In Miliseconds */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Global variable definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Local variable definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
portTickType dechatterStopTime[maxDI_Channels]; /* Contains tickcount Value, where*/
|
|
/* dechattering timeout occours */
|
|
|
|
UINT8 dechatterLockFlag[maxDI_Channels] = /* Channel Lock Flag */
|
|
{
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0
|
|
};
|
|
|
|
UINT32 dechatterTime[maxDI_Channels] = /* TimeDelay until dechatter timeout*/
|
|
{
|
|
10,
|
|
10,
|
|
10,
|
|
10,
|
|
10,
|
|
10,
|
|
10,
|
|
10,
|
|
10,
|
|
10,
|
|
10
|
|
};
|
|
|
|
// \MARK NEW PINSETTINGS FOR TESTER (2)
|
|
#if (PINSET_TESTER == 2)
|
|
t_output outputPins[maxDO_Channels] =
|
|
{
|
|
{ PORT4_BASE_ADDR, BIT(8) }, // DOUT0
|
|
{ PORT4_BASE_ADDR, BIT(9) }, // DOUT1
|
|
{ PORT4_BASE_ADDR, BIT(10) }, // DOUT2
|
|
{ PORT4_BASE_ADDR, BIT(11) }, // DOUT3
|
|
{ PORT4_BASE_ADDR, BIT(12) }, // DOUT4
|
|
{ PORT4_BASE_ADDR, BIT(13) }, // DOUT5
|
|
{ PORT4_BASE_ADDR, BIT(14) }, // DOUT6
|
|
{ PORT4_BASE_ADDR, BIT(15) } // DOUT7
|
|
};
|
|
#else
|
|
t_output outputPins[maxDO_Channels] =
|
|
{
|
|
{ PORT1_BASE_ADDR, BIT(0) }, // DOUT0
|
|
{ PORT1_BASE_ADDR, BIT(1) }, // DOUT1
|
|
{ PORT1_BASE_ADDR, BIT(4) }, // DOUT2
|
|
{ PORT1_BASE_ADDR, BIT(8) }, // DOUT3
|
|
{ PORT1_BASE_ADDR, BIT(9) }, // DOUT4
|
|
{ PORT1_BASE_ADDR, BIT(10) }, // DOUT5
|
|
{ PORT1_BASE_ADDR, BIT(14) }, // DOUT6
|
|
{ PORT1_BASE_ADDR, BIT(15) } // DOUT7
|
|
};
|
|
#endif
|
|
|
|
t_input inputPins[maxDI_Channels] =
|
|
{
|
|
{ PORT0_BASE_ADDR, BIT(15), NULL }, // DIN0
|
|
{ PORT0_BASE_ADDR, BIT(16), NULL }, // DIN1
|
|
{ PORT0_BASE_ADDR, BIT(17), NULL }, // DIN2
|
|
{ PORT0_BASE_ADDR, BIT(18), NULL }, // DIN3
|
|
{ PORT0_BASE_ADDR, BIT(24), NULL }, // DIN4
|
|
{ PORT0_BASE_ADDR, BIT(25), NULL }, // DIN5
|
|
{ PORT0_BASE_ADDR, BIT(26), NULL }, // DIN6
|
|
{ PORT0_BASE_ADDR, BIT(27), NULL }, // DIN7
|
|
{ PORT0_BASE_ADDR, BIT(28), NULL }, // DIN8
|
|
{ PORT0_BASE_ADDR, BIT(29), NULL }, // DIN9
|
|
{ PORT0_BASE_ADDR, BIT(30), NULL } // DIN10
|
|
};
|
|
|
|
BOOLEAN dioActive = FALSE;
|
|
xQueueHandle dispatchedIsrQueue= 0;
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Local function definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static void setMaskDirRegisters(void);
|
|
static void enableChannelInterrupt(UINT8 channel);
|
|
static void disableChannelInterrupt(UINT8 channel);
|
|
static void isrDispatchTask(void *pvParameters);
|
|
static BOOLEAN hasTimeoutPast( UINT32 endTick );
|
|
static void startDechatterInput (UINT8 ChannelNumber, t_di_mode Edge);
|
|
static void endDechatterInput (void);
|
|
static void callAllCallbacks(t_callbackListItem *pCallbackList, t_di_mode detectedEdge);
|
|
|
|
|
|
|
|
void dioInit(void)
|
|
{
|
|
SCS |= (1UL<<0); /* GPIOM in SCS to fast IO */
|
|
|
|
setMaskDirRegisters(); /* Init channel Registers */
|
|
dioActive= TRUE; /* Set global dioAcitve */
|
|
|
|
/* Create queue and Task for ISR-displatching */
|
|
dispatchedIsrQueue = xQueueCreate( DISPATCH_QUEUE_SIZE, sizeof(t_IsrDispatchQueueItem));
|
|
xTaskCreate(isrDispatchTask, ( signed portCHAR * ) "dioIsrDispatcher",
|
|
configMINIMAL_STACK_SIZE, NULL, DISPATCH_TASK_PRIO, NULL);
|
|
|
|
/* Enable GPIO interrupt */
|
|
portENTER_CRITICAL();
|
|
{
|
|
VICIntSelect &= ~(VIC_CHAN_TO_MASK(VIC_CHAN_NUM_EINT3));
|
|
VICIntEnClr = VIC_CHAN_TO_MASK(VIC_CHAN_NUM_EINT3);
|
|
VICVectAddr17 = (void *)gpioISR;
|
|
VICVectCntl7 = 0x01;
|
|
VICIntEnable = VIC_CHAN_TO_MASK(VIC_CHAN_NUM_EINT3);
|
|
}
|
|
portEXIT_CRITICAL();
|
|
|
|
// \MARK NEW PINSETTINGS FOR TESTER (2)
|
|
#if (PINSET_TESTER == 2)
|
|
/* Init both MUX lines as Outputs */
|
|
DIO_MUX_DIR |= (DIN_MUX_BIT | DOUT_MUX_BIT);
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
void dio_inMuxEn (BOOLEAN mode)
|
|
{
|
|
// \MARK NEW PINSETTINGS FOR TESTER (2)
|
|
#if (PINSET_TESTER == 2)
|
|
if (mode == TRUE)
|
|
{
|
|
DIN_MUX_SET;
|
|
}
|
|
else
|
|
{
|
|
DIN_MUX_CLR;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void dio_outMuxEn (BOOLEAN mode)
|
|
{
|
|
// \MARK NEW PINSETTINGS FOR TESTER (2)
|
|
#if (PINSET_TESTER == 2)
|
|
if (mode == TRUE)
|
|
{
|
|
DOUT_MUX_SET;
|
|
}
|
|
else
|
|
{
|
|
DOUT_MUX_CLR;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
BOOLEAN dio_inMuxRB (void)
|
|
{
|
|
// \MARK NEW PINSETTINGS FOR TESTER (2)
|
|
#if (PINSET_TESTER == 2)
|
|
if (DIO_MUX_SET & DIN_MUX_BIT)
|
|
{
|
|
/* MUX of digital input is switched to Extension Board */
|
|
return (TRUE);
|
|
}
|
|
else
|
|
{
|
|
/* MUX of digital input is switched to Main Board */
|
|
return (FALSE);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
BOOLEAN dio_outMuxRB (void)
|
|
{
|
|
// \MARK NEW PINSETTINGS FOR TESTER (2)
|
|
#if (PINSET_TESTER == 2)
|
|
if (DIO_MUX_SET & DOUT_MUX_BIT)
|
|
{
|
|
/* MUX of digital input is switched to Extension Board */
|
|
return (TRUE);
|
|
}
|
|
else
|
|
{
|
|
/* MUX of digital input is switched to Main Board */
|
|
return (FALSE);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
RESULT dioRegisterCallback (t_dio_callbackfunc pFunc, UINT8 channel, t_di_mode mode)
|
|
{
|
|
RESULT result = OK;
|
|
|
|
disableChannelInterrupt(channel);
|
|
|
|
// Create item
|
|
t_callbackListItem *newCallbackListItem =
|
|
(t_callbackListItem *) pvPortMalloc(sizeof(t_callbackListItem));
|
|
if (newCallbackListItem == NULL)
|
|
{
|
|
result = ERROR;
|
|
} else
|
|
{
|
|
if (inputPins[channel].pCallbackList == NULL)
|
|
{
|
|
enableChannelInterrupt(channel);
|
|
}
|
|
|
|
// Fill list item
|
|
newCallbackListItem->pCallback = pFunc;
|
|
newCallbackListItem->mode = mode;
|
|
|
|
// Add to front of list
|
|
newCallbackListItem->next = inputPins[channel].pCallbackList;
|
|
inputPins[channel].pCallbackList = newCallbackListItem;
|
|
}
|
|
|
|
enableChannelInterrupt(channel);
|
|
|
|
return result;
|
|
}
|
|
|
|
/** \brief Remove register callback function for digital input
|
|
* \retval OK Callback was removed succesfully
|
|
* \retval ERROR Failed to remove Callback-function from channel
|
|
*/
|
|
RESULT dioRemoveCallback(t_dio_callbackfunc pFunc, UINT8 channel)
|
|
{
|
|
RESULT result = OK;
|
|
|
|
disableChannelInterrupt(channel);
|
|
|
|
// Check if channel has callback list
|
|
if (inputPins[channel].pCallbackList == NULL)
|
|
{
|
|
result = ERROR;
|
|
} else
|
|
{
|
|
BOOLEAN callbackFound = FALSE;
|
|
t_callbackListItem * previousItem= NULL;
|
|
t_callbackListItem * currentItem = inputPins[channel].pCallbackList;
|
|
|
|
// Find callbackfunc
|
|
while ((!callbackFound) && (currentItem != NULL))
|
|
{
|
|
callbackFound = (currentItem->pCallback == pFunc);
|
|
|
|
if (!callbackFound)
|
|
{
|
|
previousItem = currentItem;
|
|
currentItem = currentItem->next;
|
|
}
|
|
}
|
|
|
|
if (callbackFound)
|
|
{
|
|
if (previousItem == NULL)
|
|
{
|
|
// Remove first item from list
|
|
inputPins[channel].pCallbackList = currentItem->next;
|
|
} else
|
|
{
|
|
// Remove list item
|
|
previousItem->next = currentItem->next;
|
|
}
|
|
vPortFree(currentItem); // Release resources of listitem
|
|
} else
|
|
{
|
|
result = FALSE;
|
|
}
|
|
}
|
|
|
|
if (inputPins[channel].pCallbackList != NULL)
|
|
{
|
|
enableChannelInterrupt(channel);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/** \brief Read digital input.*/
|
|
BOOLEAN dioRead(UINT8 device, /**< 0 = Self, 1..32 = Remote device */
|
|
UINT8 channel /**< 0..10 = valid, 11..255 = future use */
|
|
)
|
|
{
|
|
BOOLEAN Result;
|
|
volatile UINT32 *gpioRegister;
|
|
|
|
if (device == 0)
|
|
{
|
|
gpioRegister = (UINT32 *)(inputPins[channel].portBaseAddr + PIN_OFFSET);
|
|
|
|
// device is now ignored, future implementation
|
|
|
|
// Get result
|
|
if (*gpioRegister & inputPins[channel].pinMask)
|
|
{
|
|
Result = FALSE;
|
|
}
|
|
else
|
|
{
|
|
Result = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Result = bpecDioRead( device, channel );
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
/** \brief Readback digital outputs.*/
|
|
BOOLEAN dioReadBack(UINT8 device, /**< 0 = Self, 1..32 = Remote device */
|
|
UINT8 channel /**< 0..7 = valid, 8..255 = future use */
|
|
)
|
|
{
|
|
BOOLEAN Result;
|
|
volatile UINT32 *gpioRegister;
|
|
|
|
if (device == 0)
|
|
{
|
|
gpioRegister = (UINT32 *)(outputPins[channel].portBaseAddr + PIN_OFFSET);
|
|
|
|
// device is now ignored, future implementation
|
|
|
|
// Get result
|
|
// NOTE: Input signal is inverted
|
|
if (*gpioRegister & outputPins[channel].pinMask)
|
|
{
|
|
Result = TRUE;
|
|
} else
|
|
{
|
|
Result = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Result = bpecDioReadBack( device, channel );
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
/** \brief Write digital outputs.*/
|
|
void dioWrite(UINT8 device, /**< 0 = Self, 1..32 = Remote device */
|
|
UINT8 channel, /**< 0..7 = valid, 8..255 = future use */
|
|
BOOLEAN data)
|
|
{
|
|
volatile UINT32 *gpioRegister;
|
|
|
|
if (device == 0)
|
|
{
|
|
if (data == TRUE)
|
|
{
|
|
gpioRegister = (UINT32 *)(outputPins[channel].portBaseAddr
|
|
+ SET_OFFSET);
|
|
*gpioRegister = outputPins[channel].pinMask;
|
|
}
|
|
else
|
|
{
|
|
gpioRegister = (UINT32 *)(outputPins[channel].portBaseAddr
|
|
+ CLR_OFFSET);
|
|
*gpioRegister = outputPins[channel].pinMask;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bpecWriteDioValue(device, channel, data);
|
|
}
|
|
}
|
|
|
|
void setMaskDirRegisters()
|
|
{
|
|
int i;
|
|
volatile UINT32 *gpioRegister;
|
|
|
|
for (i=0; i< maxDO_Channels; i++)
|
|
{
|
|
// Clear bit in mask Register
|
|
gpioRegister = (UINT32 *)(outputPins[i].portBaseAddr + MASK_OFFSET);
|
|
*gpioRegister &= ~(outputPins[i].pinMask);
|
|
|
|
// Set direction bit to output
|
|
gpioRegister = (UINT32 *)(outputPins[i].portBaseAddr + DIR_OFFSET);
|
|
*gpioRegister |= outputPins[i].pinMask;
|
|
}
|
|
|
|
for (i=0; i< maxDI_Channels; i++)
|
|
{
|
|
// Clear bit in maskRegister
|
|
gpioRegister = (UINT32 *)(inputPins[i].portBaseAddr + MASK_OFFSET);
|
|
*gpioRegister &= ~(inputPins[i].pinMask);
|
|
|
|
// Set direction bit to input
|
|
gpioRegister = (UINT32 *)(inputPins[i].portBaseAddr + DIR_OFFSET);
|
|
*gpioRegister &= ~(inputPins[i].pinMask);
|
|
|
|
// Reset callback functions
|
|
inputPins[i].pCallbackList = NULL;
|
|
}
|
|
}
|
|
|
|
void enableChannelInterrupt(UINT8 channel)
|
|
{
|
|
if (inputPins[channel].portBaseAddr == PORT0_BASE_ADDR)
|
|
{
|
|
IO0_INT_CLR = inputPins[channel].pinMask;
|
|
IO0_INT_EN_R |= inputPins[channel].pinMask;
|
|
IO0_INT_EN_F |= inputPins[channel].pinMask;
|
|
}
|
|
else
|
|
{
|
|
IO2_INT_CLR = inputPins[channel].pinMask;
|
|
IO2_INT_EN_R |= inputPins[channel].pinMask;
|
|
IO2_INT_EN_F |= inputPins[channel].pinMask;
|
|
}
|
|
}
|
|
|
|
void disableChannelInterrupt(UINT8 channel)
|
|
{
|
|
if (inputPins[channel].portBaseAddr == PORT0_BASE_ADDR)
|
|
{
|
|
IO0_INT_EN_R &= ~BIT(inputPins[channel].pinMask);
|
|
IO0_INT_EN_F &= ~BIT(inputPins[channel].pinMask);
|
|
}
|
|
else
|
|
{
|
|
IO2_INT_EN_R &= ~BIT(inputPins[channel].pinMask);
|
|
IO2_INT_EN_F &= ~BIT(inputPins[channel].pinMask);
|
|
}
|
|
}
|
|
|
|
void isrDispatchTask(void *pvParameters)
|
|
{
|
|
t_IsrDispatchQueueItem dispatchItem;
|
|
UINT32 channelcnt;
|
|
|
|
do /* As long as active */
|
|
{
|
|
/* If an Input Interrupt occures, enter if Statement */
|
|
if (xQueueReceive(dispatchedIsrQueue, &dispatchItem, Int_queue_time))
|
|
{
|
|
/* Check for each single Channel, which one is active */
|
|
for (channelcnt=0; channelcnt < maxDI_Channels; channelcnt++)
|
|
{
|
|
/* Go further if CallBack exists for corresponding Channel */
|
|
if (inputPins[channelcnt].pCallbackList != NULL)
|
|
{
|
|
/* Check if this bit is active */
|
|
int portIndex = (inputPins[channelcnt].portBaseAddr
|
|
== PORT0_BASE_ADDR ? 0 : 1);
|
|
|
|
/* Check if Interrupt occured from a RISING EDGE */
|
|
if (dispatchItem.riseInterrupts[ portIndex ]
|
|
& inputPins[channelcnt].pinMask)
|
|
{ /* Rising Edge Interrupt detected */
|
|
if (dechatterTime[channelcnt] == 0)
|
|
{ /* If dechatterTime is set to ZERO */
|
|
/* call Callback directly */
|
|
callAllCallbacks(
|
|
inputPins[channelcnt].pCallbackList,
|
|
RISING_EDGE);
|
|
}
|
|
else /* If there is a dechattering Time */
|
|
{ /* Start dechattering the Input */
|
|
startDechatterInput(channelcnt, RISING_EDGE);
|
|
}
|
|
}
|
|
|
|
/* Check if Interrupt occured from a FALLING EDGE */
|
|
if (dispatchItem.fallInterrupts[ portIndex ]
|
|
& inputPins[channelcnt].pinMask)
|
|
{ /* Falling Edge Interrupt detected */
|
|
if (dechatterTime[channelcnt] == 0)
|
|
{ /* If dechatterTime is set to ZERO */
|
|
/* call Callback directly */
|
|
callAllCallbacks(
|
|
inputPins[channelcnt].pCallbackList,
|
|
FALLING_EDGE);
|
|
}
|
|
else /* if there is a dechattering Time */
|
|
{ /* Start dechattering the Input */
|
|
startDechatterInput(channelcnt, FALLING_EDGE);
|
|
}
|
|
}
|
|
} /* EndIf CallBack exists Check */
|
|
} /* End of FOR Loop */
|
|
} /* End Check for occuring Interrupt */
|
|
|
|
|
|
endDechatterInput(); /* Call dechatter monitor Function */
|
|
|
|
} while (dioActive == TRUE);
|
|
}
|
|
|
|
|
|
void startDechatterInput(UINT8 ChannelNumber, t_di_mode Edge)
|
|
{
|
|
|
|
/* If corresponding Channel is currently not monitored */
|
|
if (dechatterLockFlag[ChannelNumber] == 0)
|
|
{
|
|
/* Set dechatter Timer */
|
|
dechatterStopTime[ChannelNumber] = xTaskGetTickCount()
|
|
+ dechatterTime[ChannelNumber];
|
|
/* Handle type of detected Edge in channel Lock Flag */
|
|
switch (Edge)
|
|
{
|
|
case RISING_EDGE:
|
|
dechatterLockFlag[ChannelNumber] = 1;
|
|
break;
|
|
case FALLING_EDGE:
|
|
dechatterLockFlag[ChannelNumber] = 2;
|
|
break;
|
|
// case BOTH_EDGES:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* If come here, an already monitored Channel causes a new Interrupt
|
|
* (which means, within the Timer a new Edge occured)
|
|
* This is a chatter!
|
|
* Reload the Timer!
|
|
*/
|
|
else
|
|
{
|
|
dechatterStopTime[ChannelNumber] = xTaskGetTickCount()
|
|
+ dechatterTime[ChannelNumber];
|
|
}
|
|
|
|
}
|
|
void endDechatterInput(void)
|
|
{
|
|
UINT32 channelcnt;
|
|
|
|
/* Check every single Channel */
|
|
for (channelcnt = 0; channelcnt < maxDI_Channels; channelcnt++)
|
|
{
|
|
/* If Timeout for corresponding channel occured */
|
|
if (hasTimeoutPast( dechatterStopTime[channelcnt]) )
|
|
{
|
|
/* Switch corresponding to the former detected Edge */
|
|
switch (dechatterLockFlag[channelcnt])
|
|
{
|
|
case 1: /* a Rising Edge was dechattered */
|
|
/* Is Input still High? If Yes, channel is dechattered */
|
|
if (dioRead(0, channelcnt) == TRUE)
|
|
{ /* Call Callback Functions */
|
|
callAllCallbacks(inputPins[channelcnt].pCallbackList,
|
|
RISING_EDGE);
|
|
}
|
|
dechatterLockFlag[channelcnt] = 0; /* release Lock Flag */
|
|
break;
|
|
|
|
case 2: /* a Falling Edge was dechattered */
|
|
/* Is Input still Low? If Yes, channel is dechattered */
|
|
if (dioRead(0, channelcnt) == FALSE)
|
|
{ /* Call Callback Functions */
|
|
callAllCallbacks(inputPins[channelcnt].pCallbackList,
|
|
FALLING_EDGE);
|
|
}
|
|
dechatterLockFlag[channelcnt] = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void callAllCallbacks(t_callbackListItem *pCallbackList, t_di_mode detectedEdge)
|
|
{
|
|
while (pCallbackList != NULL)
|
|
{
|
|
if ( (pCallbackList->mode == detectedEdge) || (pCallbackList->mode
|
|
== BOTH_EDGES))
|
|
{
|
|
// Call the callback
|
|
pCallbackList->pCallback();
|
|
}
|
|
|
|
// Check next item
|
|
pCallbackList = pCallbackList->next;
|
|
}
|
|
}
|
|
|
|
void dioSetDechatterTime(UINT8 channel, UINT32 time)
|
|
{
|
|
dechatterTime[channel] = time;
|
|
}
|
|
|
|
|
|
BOOLEAN hasTimeoutPast( UINT32 endTick )
|
|
{
|
|
UINT32 nowTick = xTaskGetTickCount();
|
|
|
|
if (nowTick >= endTick)
|
|
{
|
|
if ((nowTick - endTick) > 0x0000FFFF)
|
|
{
|
|
// the endTick has gone through 0 point, nowTick is at end of range
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
// nowTick passed endTick.
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((endTick - nowTick) > 0x0000FFFF)
|
|
{
|
|
|
|
// the endTick was at end of range, nowTick has gone through 0 point
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
// nowTick still has to pass endTick
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|