Skip to content

Commit 1ca00e6

Browse files
authored
Add discrete, continuous modes to Binary Counter (#445)
* Change binary counter to have discrete or continuous modes. * Limit min k to 1 instead of 0. * Add a screensaver to Binary Counter
1 parent 25301f2 commit 1ca00e6

2 files changed

Lines changed: 77 additions & 7 deletions

File tree

software/contrib/binary_counter.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ counter.
1212
|---------------|-------------------------------------------------------------------|
1313
| `din` | Input gate signal |
1414
| `ain` | CV input to control `k` |
15-
| `b1` | Manual gate signal |
15+
| `b1` | Change between discrete or continuous modes |
1616
| `b2` | Reset `n` to zero |
1717
| `k1` | Control for `k` |
1818
| `k2` | Attenuator for `ain` |
@@ -23,6 +23,28 @@ counter.
2323
| `cv5` | 16s-bit output |
2424
| `cv6` | Most significant bit output |
2525

26+
In `discrete` mode (default) all outputs go low when `din` goes low.
27+
28+
In `continuous` mode the outputs stay on across consecutive values.
29+
30+
```
31+
k = 1
32+
33+
din
34+
__ __ __ __ __ __ __ __ __
35+
__| |__| |__| |__| |__| |__| |__| |__| |__| |__
36+
. . . . . . . . .
37+
cv2 (discrete). . . . . . .
38+
. .__ .__ .__ .__ .__ .__ . .
39+
________| |__| |__| |__| |__| |__| |______________
40+
. . . . . . . . .
41+
cv2 (continuous) . . . . . .
42+
. .___________________________________. .
43+
________| . . . . . |___________
44+
n . . . . . . . . .
45+
0 1 2 3 4 5 6 7 8 9
46+
```
47+
2648
## Configuration
2749

2850
This program has the following configuration options:

software/contrib/binary_counter.py

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,24 @@
1515
from europi_script import EuroPiScript
1616

1717
from experimental.math_extras import gray_encode
18+
from experimental.screensaver import OledWithScreensaver
1819

1920
import configuration
2021

2122

2223
class BinaryCounter(EuroPiScript):
2324
MAX_N = (1 << NUM_CVS) - 1
2425

26+
MODE_DISCRETE = 0
27+
MODE_CONTINUOUS = 1
28+
N_MODES = 2
29+
2530
def __init__(self):
2631
super().__init__()
32+
self.load_state()
33+
self.state_dirty = False
34+
35+
self.ssoled = OledWithScreensaver()
2736

2837
self.n = 0
2938
self.k = int(
@@ -36,9 +45,7 @@ def __init__(self):
3645

3746
din.handler(self.on_gate_rise)
3847
din.handler_falling(self.on_gate_fall)
39-
b1.handler(self.on_gate_rise)
40-
b1.handler_falling(self.on_gate_fall)
41-
48+
b1.handler(self.cycle_mode)
4249
b2.handler(self.reset)
4350

4451
@classmethod
@@ -51,14 +58,32 @@ def config_points(cls):
5158
),
5259
]
5360

61+
def load_state(self):
62+
cfg = self.load_state_json()
63+
self.mode = cfg.get("mode", self.MODE_DISCRETE)
64+
65+
def save_state(self):
66+
cfg = {
67+
"mode": self.mode
68+
}
69+
self.save_state_json(cfg)
70+
self.state_dirty = False
71+
72+
def cycle_mode(self):
73+
self.mode = (self.mode + 1) % self.N_MODES
74+
self.state_dirty = True
75+
self.ssoled.notify_user_interaction()
76+
5477
def on_gate_rise(self):
5578
self.gate_recvd = True
5679

5780
def on_gate_fall(self):
58-
turn_off_all_cvs()
81+
if self.mode == self.MODE_DISCRETE:
82+
turn_off_all_cvs()
5983

6084
def reset(self):
6185
self.n = 0
86+
self.ssoled.notify_user_interaction()
6287

6388
def set_outputs(self):
6489
if self.config.USE_GRAY_ENCODING:
@@ -74,19 +99,42 @@ def set_outputs(self):
7499

75100

76101
def main(self):
102+
current_k1 = 0
103+
current_k2 = 0
104+
prev_k1 = 0
105+
prev_k2 = 0
106+
WIGGLE_THRESHOLD = 0.05
107+
77108
while True:
109+
current_k1 = k1.percent()
110+
current_k2 = k2.percent()
111+
if (
112+
abs(prev_k1 - current_k1) >= WIGGLE_THRESHOLD
113+
or abs(prev_k2 - current_k2) >= WIGGLE_THRESHOLD
114+
):
115+
self.ssoled.notify_user_interaction()
116+
prev_k1 = current_k1
117+
prev_k2 = current_k2
118+
78119
self.k = int(
79120
(
80-
k1.percent() + k2.percent() * ain.percent()
121+
current_k1 + current_k2 * ain.percent()
81122
) * self.MAX_N
82123
)
124+
# minimum of 1; k==0 will do nothing, which isn't interesting
125+
if self.k == 0:
126+
self.k = 1
127+
128+
if self.state_dirty:
129+
self.save_state()
83130

84131
if self.gate_recvd:
85132
self.set_outputs()
86133
self.n = (self.n + self.k) & self.MAX_N
87134
self.gate_recvd = False
88135

89-
oled.centre_text(f"""k = {self.k}
136+
self.ssoled.centre_text(f"""{'Discrete' if self.mode == self.MODE_DISCRETE else 'Continuous'}
137+
k = {self.k}
90138
{self.n:06b}""")
91139

92140

0 commit comments

Comments
 (0)