-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Start working on a basic RTC-based random sequencer
- Loading branch information
Showing
4 changed files
with
152 additions
and
0 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Daily Random | ||
|
||
Generates pseudo-random gate and CV patterns based on the current date and time. | ||
|
||
## I/O Assignments | ||
|
||
- `ain`: not used | ||
- `din`: external clock input | ||
- `b1`: not used | ||
- `b2`: not used | ||
- `k1`: not used | ||
- `k2`: not used | ||
- `cv1`: daily gate sequence (updates at midnight UTC) | ||
- `cv2`: hourly gate sequence (updates at the top of every hour) | ||
- `cv3`: minute gate sequence (updates at the top of every minute) | ||
- `cv4`: daily CV sequence (updates at midnight UTC) | ||
- `cv5`: hourly CV sequence (updates at the top of every hour) | ||
- `cv6`: minute CV sequence (updates at the top of every minute) | ||
|
||
## Required Hardware | ||
|
||
This script _can_ be used on a normal EuroPi, but will result in highly predictable | ||
patterns. For best result, connect a Realtime Clock (RTC) to EuroPi's secondary I2C | ||
header pins, located on the underside of the board. | ||
|
||
## Installing the clock | ||
|
||
TODO: pictures of mounting a DS3231 | ||
|
||
## Configuring the clock | ||
|
||
The default external I2C settings from `europi_config` should be used, unless you have | ||
a specific need to change them in `config/EuroPiConfig.json`: | ||
```json | ||
{ | ||
"EXTERNAL_I2C_SDA": 2, | ||
"EXTERNAL_I2C_SCL": 3, | ||
"EXTERNAL_I2C_CHANNEL": 1, | ||
"EXTERNAL_I2C_FREQUENCY": 100000, | ||
"EXTERNAL_I2C_TIMEOUT": 50000, | ||
} | ||
``` | ||
|
||
You will also need to edit `config/ExperimentalConfig.json`: | ||
```json | ||
{ | ||
"RTC_IMPLEMENTATION": "ds3231" | ||
} | ||
``` | ||
|
||
Once installed and configured, if you have not already set the clock's time, you can do so by | ||
connecting your EuroPi to Thonny's Python terminal and running the following commands: | ||
```python | ||
from experimental.rtc import clock, Month, Weekday | ||
clock.source.set_datetime(clock.source.set_datetime((2025, Month.JUNE, 14, 22, 59, 0, Weekday.THURSDAY))) | ||
``` | ||
You should change the day and time to match the current UTC time. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
from europi import * | ||
from europi_script import EuroPiScript | ||
|
||
from experimental.rtc import clock | ||
|
||
import random | ||
|
||
|
||
class DailyRandom(EuroPiScript): | ||
""" | ||
Generates a set of pseudo-random gate and CV sequences every day | ||
This script requires a realtime clock. Please refer to | ||
experimental.clocks for supported clocks. | ||
If no RTC is installed & configured, the default clock will be used, | ||
but this will generate the same pattern every time the module is | ||
restarted. | ||
""" | ||
|
||
SEQUENCE_LENGTH = 16 | ||
|
||
def __init__(self): | ||
super().__init__() | ||
|
||
current_time = clock.now() | ||
self.regenerate_sequences(current_time) | ||
|
||
self.sequence_index = 0 | ||
|
||
@din.handler | ||
def advance_sequence(): | ||
self.sequence_index += 1 | ||
|
||
def regenerate_sequences(self, datetime): | ||
(year, month, day, hour, minute) = datetime[0:5] | ||
|
||
seed_1 = year ^ month ^ day | ||
seed_2 = year ^ month ^ day ^ hour | ||
seed_3 = year ^ month ^ day ^ hour ^ minute | ||
|
||
def generate_gates(seed): | ||
random.seed(seed) | ||
bits = random.getrandbits(self.SEQUENCE_LENGTH) | ||
pattern = [] | ||
for i in range(self.SEQUENCE_LENGTH): | ||
pattern.append(bits & 0x01) | ||
bits = bits >> 1 | ||
return pattern | ||
|
||
def generate_cv(seed): | ||
random.seed(seed) | ||
pattern = [] | ||
for i in range(self.SEQUENCE_LENGTH): | ||
pattern.append(random.random() * europi_config.MAX_OUTPUT_VOLTAGE) | ||
return pattern | ||
|
||
self.sequences = [ | ||
generate_gates(seed_1), | ||
generate_gates(seed_2), | ||
generate_gates(seed_3), | ||
generate_cv(seed_1), | ||
generate_cv(seed_2), | ||
generate_cv(seed_3), | ||
] | ||
|
||
def main(self): | ||
# clear the display | ||
oled.fill(0) | ||
oled.show() | ||
|
||
while True: | ||
# regenerate the patterns when the day rolls over | ||
current_time = clock.now() | ||
self.regenerate_sequences(current_time) | ||
|
||
for i in range(len(cvs)): | ||
if i < len(cvs) // 2: | ||
cvs[i].voltage(self.sequences[i][self.sequence_index % self.SEQUENCE_LENGTH] * europi_config.GATE_VOLTAGE) | ||
else: | ||
cvs[i].voltage(self.sequences[i][self.sequence_index % self.SEQUENCE_LENGTH] * europi_config.MAX_OUTPUT_VOLTAGE) | ||
|
||
|
||
if __name__ == "__main__": | ||
DailyRandom().main() |
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