""" micronEC: Simple, easy-to-use hardware counter. Raspberry Pico basis. 16*2 LCD display. micronEC. Copyright (C) 2023 Benjamin Burkhardt This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ from machine import Pin from time import sleep from utime import ticks_ms """ Counter give a basic counter class with a name and value """ class Counter: def __init__(self, name="C1", value = 0): # init_value may be smaller than 0 self.value = int(value) self.name = str(name) def __str__(self): return str(self.name); def __int__(self): return int(self.value); def __add__(self, x): counter = Counter(value=self.value+int(x)) return counter def __sub__(self, x): counter = Counter(value=self.value-int(x)) return counter def increment(self): self.value += 1 """ CounterArray: provides an easy-to-use interface for the counter class. """ class CounterArray: def __init__(self, counter_number = 1, counter_names = ["Counter 1"]): self._counters = {} if len(counter_names) < counter_number: raise IndexError("counter_names list MUST contain names for all counters.") elif len(counter_names) > counter_number: print("[WARN] [CounterArray] More counter names are given than counters wanted. Ignoring the overflow.") for i in range(counter_number): self._counters[i] = Counter(counter_names[i]) def add_counter(self, counter: Counter): # Function # add a counter to the counterarray's internal _counter dict self._counters[len(self._counters)] = counter return True def remove_counter(self, key): # Function # pop a counter out of the counterarrays internal _counter dict with the given key self._counters.pop(key) return True def get_counter(self, key): # Function # get the Counter class object with the given key return self._counters[key] def register_listener(self, pins: dict, changed_callback=lambda: None): # Function: # listens for btn presses on specified pins # Parameter: pins # should be a dict of the form {COUNTER_ID:PIN, ...} # where COUNTER_ID is the key of the counter to increment in the # internal _counters dict and PIN is the pin to listen on # Parameter: changed_callback # is called without parameters, every time a button was pressed inputs = {} for counter_id, pin in pins.items(): inputs[counter_id] = Pin(pin, Pin.IN, Pin.PULL_DOWN) self.last_time = 0 def press_handler(pin, inputs, _counters, counterarray, changed_callback): for counter_id, p in inputs.items(): if p == pin: # now we have the pin where the button got pressed new_time = ticks_ms() if (new_time - counterarray.last_time) > 150: _counters[counter_id] += 1 counterarray.last_time = new_time changed_callback() for counter_id, pin in inputs.items(): try: self._counters[counter_id] pin.irq(trigger=Pin.IRQ_FALLING, handler=lambda p: press_handler(p, inputs, self._counters, self, changed_callback)) except KeyError: print("[ERROR] [Counter().register_listener] Error while registering counter-pin-pair (counter_id=" + str(counter_id) + ", pin=" + str(pin) + "). Ignoring this pair.")