123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- /*
- * sequence.c
- *
- * Copyright (c) 2024 Thomas Buck (thomas@xythobuz.de)
- *
- * 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.
- *
- * See <http://www.gnu.org/licenses/>.
- */
-
- #include <stdio.h>
- #include "pico/stdlib.h"
-
- #include "led.h"
- #include "sequence.h"
-
- #define MAX_BEATS 32
-
- static uint32_t ms_per_beat = 500;
- static uint32_t beats = 16;
- static uint32_t last_t = 0;
- static uint32_t last_i = 0;
-
- static enum channels sequence[MAX_BEATS] = {0};
-
- void sequence_init(void) {
- last_t = to_ms_since_boot(get_absolute_time());
- last_i = 0;
- }
-
- void sequence_set_bpm(uint32_t new_bpm) {
- ms_per_beat = 60000 / new_bpm;
- }
-
- void sequence_set_beats(uint32_t new_beats) {
- beats = (new_beats <= MAX_BEATS) ? new_beats : MAX_BEATS;
- }
-
- static void sequence_set(uint32_t beat, enum channels ch, bool value) {
- if (beat < MAX_BEATS) {
- if (value) {
- sequence[beat] |= ch;
- } else {
- sequence[beat] &= ~ch;
- }
- }
- }
-
- static bool sequence_get(uint32_t beat, enum channels ch) {
- if (beat < MAX_BEATS) {
- return (sequence[beat] & ch) != 0;
- }
- return false;
- }
-
- void sequence_handle_button_loopstation(enum buttons btn, bool rec) {
- switch (btn) {
- case BTN_A:
- // TODO trigger gpio impulse
- break;
-
- case BTN_B:
- // TODO trigger gpio impulse
- break;
-
- case BTN_C:
- // TODO trigger gpio impulse
- break;
-
- default:
- break;
- }
-
- if (rec) {
- uint32_t beat = 42; // TODO!!
-
- switch (btn) {
- case BTN_A:
- sequence_set(beat, CH_KICK, true);
- break;
-
- case BTN_B:
- sequence_set(beat, CH_SNARE, true);
- break;
-
- case BTN_C:
- sequence_set(beat, CH_HIHAT, true);
- break;
-
- default:
- break;
- }
- }
- }
-
- void sequence_handle_button_drummachine(enum buttons btn) {
- uint32_t beat = 42; // TODO!!
-
- switch (btn) {
- case BTN_A:
- sequence_set(beat, CH_KICK, !sequence_get(beat, CH_KICK));
- break;
-
- case BTN_B:
- sequence_set(beat, CH_SNARE, !sequence_get(beat, CH_SNARE));
- break;
-
- case BTN_C:
- sequence_set(beat, CH_HIHAT, !sequence_get(beat, CH_HIHAT));
- break;
-
- default:
- break;
- }
- }
-
- void sequence_run(void) {
- uint32_t now = to_ms_since_boot(get_absolute_time());
-
- if ((last_t + ms_per_beat) >= now) {
- uint32_t i = last_i + 1;
- if (i >= beats) i = 0;
-
- led_set(last_i, false);
- led_set(i, true);
-
- if (sequence[i]) {
- // TODO trigger GPIO impulse
- }
-
- last_t = now;
- last_i = i;
- }
- }
|