Last active
September 29, 2022 22:49
-
-
Save yatharthb97/0ebb5a6e618c2de3720aeefbf82a708a to your computer and use it in GitHub Desktop.
Describes a class `UDCounter` or "Up - Down Counter" which is a multi-modal bidirectional counter object.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Up or Down (Bimodal) Counting Object | |
Author - Yatharth Bhasin (github → yatharthb97) | |
Describes a class `UDCounter` or "Up - Down Counter" which is a multi-modal bidirectional counter object. | |
The design of this class was inspired by Hardware counters/timers. | |
`isr` : interrupt service routine | |
""" | |
class UDCounter: | |
''' | |
Bi-directional Counter → {"up", "down_counter"} counting object. | |
Multi-modal → {"off", "trigger on overflow", "trigger on compare", "trigger on multiple compares"} | |
''' | |
def __init__(self, name): | |
''' | |
Constructor object → no arguemnets. Sets the mode to "off". | |
''' | |
self.name = name | |
self.value = 0 | |
self.reset = 0 | |
self.verbose = False | |
self.mode = "off" | |
self.turn_off() | |
def update(self): | |
''' | |
Updates the value of the counter using the updater function. | |
''' | |
self.value = self.updater(self.value) | |
def load_val(self, value): | |
''' | |
Loads the given Positive Integer value to the counter value. | |
''' | |
self.value = value | |
def set_up_counter(self, value: int): | |
''' | |
Begins up-counting after setting the counter value to the passed arguement `value`. | |
''' | |
self.updater = lambda x : x + 1 | |
self.mode = "up" | |
self.load_val(value) | |
if self.verbose: | |
print(f" •[UDCntr {self.name}] Up Counter set: {self.value}") | |
def set_down_counter(self, value: int): | |
''' | |
Begins down-counting after setting the counter value to the passed arguement `value`. | |
''' | |
self.updater = lambda x : x - 1 | |
self.mode = "down" #Bookeeping | |
self.load_val(value) | |
if self.verbose: | |
print(f" •[UDCntr {self.name}] Down Counter set: {self.value}") | |
def val(self): | |
''' | |
Reads back the counter value. | |
''' | |
return self.value | |
def turn_off(self): | |
''' | |
Turns off the counter and freezes the current count value. | |
''' | |
self.mode == "off" | |
self.updater = lambda x : x # Blank Lambda | |
if self.verbose: | |
print(f" •[UDCntr {self.name}] Counter turned off: {self.value}") | |
def trigger_on_overflow(self, overflow_val: int, isr, **kwargs): | |
''' | |
Sets up the counter to trigger a callback function `isr` or Interrupt Service Routine after each overflow. | |
The `isr` returns nothing and accepts no arguements. | |
The overflow value is set by the passed parameter `overlow_val`. The counter is reset after each overflow. | |
The reset value is determined from the kwargs - 'reset' or the set object attribute `reset`. | |
The counter must first be set to either 'up' or 'down' mode before setting this function. | |
''' | |
if(self.mode != "up" or self.mode != "down"): | |
raise Exception ("Please set direction of the counter - 'up' or 'down'. ") | |
if 'reset' in kwargs: | |
self.reset = kwargs['reset'] | |
self.mode = "trigger on overflow" | |
self.overflow = overflow_val | |
self.isr = isr | |
old_updater = self.updater | |
def overflow_updater(x): | |
x = old_updater(x) | |
if x == self.overflow: | |
self.isr() | |
x = 0 | |
return x | |
self.updater = overflow_updater | |
if self.verbose: | |
print(f" •[UDCntr {self.name}] Overflow trigger set on: {self.overfow}") | |
def trigger_on_compare(self, compare_val: int, isr, **kwargs): | |
''' | |
Sets up the counter to trigger a callback function `isr` or Interrupt Service Routine after a compare event. | |
The `isr` returns nothing and accepts no arguements. | |
The compare value is set by the passed parameter `comapre_val`. The counter is NOT reset after a compare. | |
The counter must first be set to either 'up' or 'down' mode before setting this function. | |
''' | |
if(self.mode != "up" or self.mode != "down"): | |
raise Exception ("Please set direction of the counter - 'up' or 'down'. ") | |
self.mode = "trigger on compare" | |
self.compare = value | |
self.isr = isr | |
old_updater = self.updater | |
def compare_updater(x): | |
x = old_updater(x) | |
if (x == self.compare): | |
self.isr() | |
return x | |
self.updater = compare_updater | |
if self.verbose: | |
print(f" •[UDCntr {self.name}] Compare trigger set on: {self.compare}") | |
def trigger_on_multi_compare(self, compare_vals: int, isr): | |
''' | |
Sets up the counter to trigger a callback function `isr` or Interrupt Service after a compare event. | |
The `isr` returns nothing and accepts no arguements. | |
The compare value is set by the passed parameter `comapre_val`. The counter is NOT reset after a compare. | |
After exhausting the list of compare values, the compare value is reset from the first value in the list. | |
The counter must first be set to either 'up' or 'down' mode before setting this function. | |
''' | |
if(self.mode != "up" or self.mode != "down"): | |
raise Exception("Please set direction of the counter - 'up' or 'down'. ") | |
self.mode = "trigger on multiple compares" | |
self.compare = list(compare_vals) | |
self.isr = isr | |
old_updater = self.updater | |
compare_index = 0 | |
def multi_compare_updater(x): | |
x = old_updater(x) | |
if (x == self.compare[compare_index]): | |
self.isr() | |
compare_index = comapre_index + 1 | |
if comapre_index >= len(self.compare): | |
compare_index = 0 | |
return x | |
self.updater = multi_compare_updater | |
if self.verbose: | |
print(f" •[UDCntr {self.name}] Compare trigger set on: {self.compare}") | |
def force_up(self): | |
''' | |
Forces an increment on the current value, irrespective of the counting direction. | |
''' | |
self.value = self.value + 1 | |
def force_down(self): | |
''' | |
Forces a decrement on the current value, irrespective of the counting direction. | |
''' | |
self.value = self.value - 1 | |
def summary(self): | |
''' | |
Prints a description of the counter object. | |
''' | |
print(f"Counter Object -> mode : {self.mode} | value -> {self.val()}") | |
if self.mode == "trigger on compare" : print(f"Compare Value -> {self.compare}") | |
if self.mode == "trigger on overflow" : print(f"Overflow Value -> {self.overfow}") | |
def __repr__(self): | |
''' | |
Returns the string description of the counter object. | |
''' | |
return f" <UDCounter Object> mode -> {self.mode} : current value -> {self.val()}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment