# validated: 2015-12-28 DS 4881795 athena/java/edu/wpi/first/wpilibj/DigitalGlitchFilter.java
#----------------------------------------------------------------------------
# Copyright (c) FIRST 2015. All Rights Reserved.
# Open Source Software - may be modified and shared by FRC teams. The code
# must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.
#----------------------------------------------------------------------------
import hal
import threading
from .digitalsource import DigitalSource
from .encoder import Encoder
from .counter import Counter
from .sensorbase import SensorBase
__all__ = ['DigitalGlitchFilter']
[docs]class DigitalGlitchFilter(SensorBase):
'''
Class to enable glitch filtering on a set of digital inputs.
This class will manage adding and removing digital inputs from a FPGA glitch
filter. The filter lets the user configure the time that an input must remain
high or low before it is classified as high or low.
'''
mutex = threading.Lock()
filterAllocated = [False]*3
def __init__(self):
self.channelIndex = -1
with self.mutex:
for i, v in enumerate(self.filterAllocated):
if not v:
self.channelIndex = i
self.filterAllocated[i] = True
hal.HALReport(hal.HALUsageReporting.kResourceType_DigitalFilter,
self.channelIndex, 0)
break
else:
raise ValueError("No more filters available")
[docs] def free(self):
if self.channelIndex >= 0:
with self.mutex:
self.filterAllocated[self.channelIndex] = False
self.channelIndex = -1
@staticmethod
def _setFilter(input, channelIndex):
if input is not None: # Counter might have just one input
hal.setFilterSelect(input.port, channelIndex)
selected = hal.getFilterSelect(input.port)
if selected != channelIndex:
raise ValueError('setFilterSelect(%s) failed -> %s' % (channelIndex, selected))
[docs] def add(self, input):
'''
Assigns the :class:`.DigitalSource`, :class:`.Encoder`, or
:class:`.Counter` to this glitch filter.
:param input: Object to add
'''
if isinstance(input, DigitalSource):
DigitalGlitchFilter._setFilter(input, self.channelIndex + 1)
elif isinstance(input, Encoder):
DigitalGlitchFilter._setFilter(input.aSource, self.channelIndex + 1)
DigitalGlitchFilter._setFilter(input.bSource, self.channelIndex + 1)
elif isinstance(input, Counter):
DigitalGlitchFilter._setFilter(input.upSource, self.channelIndex + 1)
DigitalGlitchFilter._setFilter(input.downSource, self.channelIndex + 1)
else:
raise ValueError("Cannot add %s to glitch filter" % input)
[docs] def remove(self, input):
'''
Removes this filter from the given input object
'''
if isinstance(input, DigitalSource):
DigitalGlitchFilter._setFilter(input, 0)
elif isinstance(input, Encoder):
DigitalGlitchFilter._setFilter(input.aSource, 0)
DigitalGlitchFilter._setFilter(input.bSource, 0)
elif isinstance(input, Counter):
DigitalGlitchFilter._setFilter(input.upSource, 0)
DigitalGlitchFilter._setFilter(input.downSource, 0)
else:
raise ValueError("Cannot remove %s from glitch filter" % input)
[docs] def setPeriodCycles(self, fpga_cycles):
'''
Sets the number of FPGA cycles that the input must hold steady to pass
through this glitch filter.
:param fpga_cycles: The number of FPGA cycles.
'''
hal.setFilterPeriod(self.channelIndex, fpga_cycles)
[docs] def setPeriodNanoSeconds(self, nanoseconds):
'''
Sets the number of nanoseconds that the input must hold steady to pass
through this glitch filter.
:param nanoseconds: The number of nanoseconds.
'''
fpga_cycles = int(nanoseconds * self.kSystemClockTicksPerMicrosecond / 4 / 1000)
self.setPeriodCycles(fpga_cycles)
[docs] def getPeriodCycles(self):
'''
Gets the number of FPGA cycles that the input must hold steady to pass
through this glitch filter.
:returns: The number of cycles.
'''
return hal.getFilterPeriod(self.channelIndex)
[docs] def getPeriodNanoSeconds(self):
'''
Gets the number of nanoseconds that the input must hold steady to pass
through this glitch filter.
:returns: The number of nanoseconds.
'''
fpga_cycles = self.getPeriodCycles()
return fpga_cycles * 1000 / (self.kSystemClockTicksPerMicrosecond / 4)