Browse Source

initial commit

Thomas Buck 1 month ago
commit
26cc67303c
19 changed files with 629 additions and 0 deletions
  1. 2
    0
      .clangd
  2. 1
    0
      .gitignore
  3. 6
    0
      .gitmodules
  4. 80
    0
      CMakeLists.txt
  5. 24
    0
      README.md
  6. 38
    0
      include/buttons.h
  7. 15
    0
      include/encoder.h
  8. 24
    0
      include/lcd.h
  9. 25
    0
      include/led.h
  10. 24
    0
      include/main.h
  11. 28
    0
      include/sequence.h
  12. 1
    0
      pico-sdk
  13. 1
    0
      pico-ssd1306
  14. 80
    0
      src/buttons.c
  15. 85
    0
      src/encoder.c
  16. 39
    0
      src/lcd.c
  17. 39
    0
      src/led.c
  18. 47
    0
      src/main.c
  19. 70
    0
      src/sequence.c

+ 2
- 0
.clangd View File

@@ -0,0 +1,2 @@
1
+CompileFlags:
2
+  CompilationDatabase: build/

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
1
+build

+ 6
- 0
.gitmodules View File

@@ -0,0 +1,6 @@
1
+[submodule "pico-sdk"]
2
+	path = pico-sdk
3
+	url = https://github.com/raspberrypi/pico-sdk
4
+[submodule "pico-ssd1306"]
5
+	path = pico-ssd1306
6
+	url = https://github.com/daschr/pico-ssd1306

+ 80
- 0
CMakeLists.txt View File

@@ -0,0 +1,80 @@
1
+# ----------------------------------------------------------------------------
2
+# Copyright (c) 2024 Thomas Buck (thomas@xythobuz.de)
3
+#
4
+# This program is free software: you can redistribute it and/or modify
5
+# it under the terms of the GNU General Public License as published by
6
+# the Free Software Foundation, either version 3 of the License, or
7
+# (at your option) any later version.
8
+#
9
+# This program is distributed in the hope that it will be useful,
10
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+# GNU General Public License for more details.
13
+#
14
+# See <http://www.gnu.org/licenses/>.
15
+# ----------------------------------------------------------------------------
16
+
17
+cmake_minimum_required(VERSION 3.13)
18
+
19
+# initialize pico-sdk from submodule
20
+include(pico-sdk/pico_sdk_init.cmake)
21
+
22
+project(gadget C CXX)
23
+set(CMAKE_C_STANDARD 11)
24
+set(CMAKE_CXX_STANDARD 17)
25
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
26
+
27
+# initialize the Raspberry Pi Pico SDK
28
+pico_sdk_init()
29
+
30
+add_executable(drumkit)
31
+
32
+target_sources(drumkit PUBLIC
33
+    src/main.c
34
+    src/lcd.c
35
+    src/buttons.c
36
+    src/encoder.c
37
+    src/sequence.c
38
+    src/led.c
39
+
40
+    pico-ssd1306/ssd1306.c
41
+)
42
+
43
+# external dependency include directories
44
+target_include_directories(drumkit PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
45
+target_include_directories(drumkit PUBLIC ${CMAKE_CURRENT_LIST_DIR}/pico-ssd1306)
46
+
47
+# enable generous warnings
48
+target_compile_options(drumkit PUBLIC
49
+    -Wall
50
+    -Wextra
51
+    -Werror
52
+    -Wshadow
53
+)
54
+
55
+# suppress some warnings for borked 3rd party files in Pico SDK
56
+set_source_files_properties(pico-sdk/lib/btstack/src/ble/sm.c PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)
57
+set_source_files_properties(pico-sdk/lib/btstack/src/btstack_hid_parser.c PROPERTIES COMPILE_FLAGS -Wno-maybe-uninitialized)
58
+set_source_files_properties(pico-sdk/src/rp2_common/pico_cyw43_driver/cyw43_driver.c PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)
59
+set_source_files_properties(pico-sdk/lib/btstack/src/classic/avdtp_util.c PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)
60
+set_source_files_properties(pico-sdk/lib/btstack/src/classic/goep_client.c PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)
61
+set_source_files_properties(pico-sdk/lib/btstack/src/classic/goep_server.c PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)
62
+set_source_files_properties(pico-sdk/src/rp2_common/hardware_flash/flash.c PROPERTIES COMPILE_FLAGS -Wno-shadow)
63
+
64
+# pull in common dependencies
65
+target_link_libraries(drumkit
66
+    pico_stdlib
67
+    hardware_i2c
68
+    hardware_adc
69
+    hardware_gpio
70
+    hardware_pwm
71
+)
72
+
73
+# enable usb output, disable uart output
74
+pico_enable_stdio_usb(drumkit 1)
75
+pico_enable_stdio_uart(drumkit 0)
76
+
77
+# fix for Errata RP2040-E5 (the fix requires use of GPIO 15)
78
+target_compile_definitions(drumkit PUBLIC PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1)
79
+
80
+pico_add_extra_outputs(drumkit)

+ 24
- 0
README.md View File

@@ -0,0 +1,24 @@
1
+# Drumkit
2
+
3
+## Hardware Connections
4
+
5
+    Pin 1    GP0    I2C SDA
6
+    Pin 2    GP1    I2C SCL
7
+
8
+    Pin 4    GP2    Output Channel A
9
+    Pin 5    GP3    Output Channel B
10
+    Pin 6    GP4    Output Channel C
11
+
12
+    Pin 7    GP5    Button 1
13
+    Pin 9    GP6    Button 2
14
+    Pin 10   GP7    Button 3
15
+    Pin 11   GP8    Button 4
16
+
17
+    Pin 12   GP9    Encoder A
18
+    Pin 14   GP10   Encoder B
19
+    Pin 15   GP11   Encoder Click
20
+
21
+    Pin 16   GP12   LED 1
22
+    Pin 17   GP13   LED 2
23
+    Pin 19   GP14   LED 3
24
+    Pin 20   GP15   LED 4

+ 38
- 0
include/buttons.h View File

@@ -0,0 +1,38 @@
1
+/*
2
+ * buttons.h
3
+ *
4
+ * Copyright (c) 2022 - 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __BUTTONS_H__
20
+#define __BUTTONS_H__
21
+
22
+#include <stdbool.h>
23
+
24
+enum buttons {
25
+    BTN_A = 0,
26
+    BTN_B,
27
+    BTN_C,
28
+    BTN_REC,
29
+    BTN_CLICK,
30
+    NUM_BTNS // count
31
+};
32
+
33
+void buttons_init(void);
34
+void buttons_callback(void (*fp)(enum buttons, bool));
35
+void buttons_run(void);
36
+
37
+#endif // __BUTTONS_H__
38
+

+ 15
- 0
include/encoder.h View File

@@ -0,0 +1,15 @@
1
+/*
2
+ * encoder.h
3
+ *
4
+ * Based on https://github.com/mathertel/RotaryEncoder/blob/master/src/RotaryEncoder.cpp
5
+ */
6
+
7
+#ifndef __ENCODER_H__
8
+#define __ENCODER_H__
9
+
10
+void encoder_init(void);
11
+int32_t encoder_pos(void);
12
+void encoder_run(void);
13
+
14
+#endif // __ENCODER_H__
15
+

+ 24
- 0
include/lcd.h View File

@@ -0,0 +1,24 @@
1
+/*
2
+ * lcd.h
3
+ *
4
+ * Copyright (c) 2024 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __LCD_H__
20
+#define __LCD_H__
21
+
22
+void lcd_init(void);
23
+
24
+#endif // __LCD_H__

+ 25
- 0
include/led.h View File

@@ -0,0 +1,25 @@
1
+/*
2
+ * led.h
3
+ *
4
+ * Copyright (c) 2024 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __LED_H__
20
+#define __LED_H__
21
+
22
+void led_init(void);
23
+void led_set(uint32_t i, bool v);
24
+
25
+#endif // __LED_H__

+ 24
- 0
include/main.h View File

@@ -0,0 +1,24 @@
1
+/*
2
+ * main.h
3
+ *
4
+ * Copyright (c) 2024 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __MAIN_H__
20
+#define __MAIN_H__
21
+
22
+
23
+
24
+#endif // __MAIN_H__

+ 28
- 0
include/sequence.h View File

@@ -0,0 +1,28 @@
1
+/*
2
+ * sequence.h
3
+ *
4
+ * Copyright (c) 2024 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __SEQUENCE_H__
20
+#define __SEQUENCE_H__
21
+
22
+void sequence_init(void);
23
+void sequence_set_bpm(uint32_t new_bpm);
24
+void sequence_set_beats(uint32_t new_beats);
25
+void sequence_set(uint32_t beat, bool value);
26
+void sequence_run(void);
27
+
28
+#endif // __SEQUENCE_H__

+ 1
- 0
pico-sdk

@@ -0,0 +1 @@
1
+Subproject commit 6a7db34ff63345a7badec79ebea3aaef1712f374

+ 1
- 0
pico-ssd1306

@@ -0,0 +1 @@
1
+Subproject commit 8467f5b06ebd7bfa7b53e4ebc83dfdc6f396e4eb

+ 80
- 0
src/buttons.c View File

@@ -0,0 +1,80 @@
1
+/*
2
+ * buttons.c
3
+ *
4
+ * Copyright (c) 2024 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include <stdio.h>
20
+#include "pico/stdlib.h"
21
+
22
+#include "buttons.h"
23
+
24
+#define DEBOUNCE_DELAY_MS 50
25
+
26
+static const uint gpio_num[NUM_BTNS] = {
27
+    5, // BTN_A
28
+    6, // BTN_B
29
+    7, // BTN_C
30
+    8, // BTN_REC
31
+    11, // BTN_CLICK
32
+};
33
+
34
+struct button_state {
35
+    uint32_t last_time;
36
+    bool current_state, last_state;
37
+};
38
+
39
+static struct button_state buttons[NUM_BTNS];
40
+static void (*callback)(enum buttons, bool) = NULL;
41
+
42
+void buttons_init(void) {
43
+    for (uint i = 0; i < NUM_BTNS; i++) {
44
+        gpio_init(gpio_num[i]);
45
+        gpio_set_dir(gpio_num[i], GPIO_IN);
46
+        gpio_pull_up(gpio_num[i]);
47
+
48
+        buttons[i].last_time = 0;
49
+        buttons[i].current_state = false;
50
+        buttons[i].last_state = false;
51
+    }
52
+}
53
+
54
+void buttons_callback(void (*fp)(enum buttons, bool)) {
55
+    callback = fp;
56
+}
57
+
58
+void buttons_run(void) {
59
+    for (uint i = 0; i < NUM_BTNS; i++) {
60
+        bool state = !gpio_get(gpio_num[i]);
61
+        uint32_t now = to_ms_since_boot(get_absolute_time());
62
+
63
+        if (state != buttons[i].last_state) {
64
+            buttons[i].last_time = now;
65
+        }
66
+
67
+        if ((now - buttons[i].last_time) > DEBOUNCE_DELAY_MS) {
68
+            if (state != buttons[i].current_state) {
69
+                printf("btn %d now %s\n", i, state ? "pressed" : "released");
70
+
71
+                buttons[i].current_state = state;
72
+                if (callback) {
73
+                    callback(i, state);
74
+                }
75
+            }
76
+        }
77
+
78
+        buttons[i].last_state = state;
79
+    }
80
+}

+ 85
- 0
src/encoder.c View File

@@ -0,0 +1,85 @@
1
+/*
2
+ * encoder.c
3
+ *
4
+ * Based on https://github.com/mathertel/RotaryEncoder/blob/master/src/RotaryEncoder.cpp
5
+ */
6
+
7
+#include <stdio.h>
8
+#include "pico/stdlib.h"
9
+
10
+#include "encoder.h"
11
+
12
+#define LATCH0 0
13
+#define LATCH3 3
14
+
15
+#define FOUR3 1 // 4 steps, Latch at position 3 only (compatible to older versions)
16
+#define FOUR0 2 // 4 steps, Latch at position 0 (reverse wirings)
17
+#define TWO03 3 // 2 steps, Latch at position 0 and 3
18
+
19
+#define ENCODER_MODE TWO03
20
+
21
+static const uint gpio_num[2] = {
22
+    9, 10
23
+};
24
+
25
+static const int8_t KNOBDIR[] = {
26
+    0, -1, 1, 0,
27
+    1, 0, 0, -1,
28
+    -1, 0, 0, 1,
29
+    0, 1, -1, 0
30
+};
31
+
32
+static int8_t oldState;
33
+static int32_t position;
34
+static int32_t positionExt;
35
+static int32_t positionExtPrev;
36
+
37
+void encoder_init(void) {
38
+    for (uint i = 0; i < 2; i++) {
39
+        gpio_init(gpio_num[i]);
40
+        gpio_set_dir(gpio_num[i], GPIO_IN);
41
+        gpio_pull_up(gpio_num[i]);
42
+    }
43
+
44
+    oldState = gpio_get(gpio_num[0]) | (gpio_get(gpio_num[1]) << 1);
45
+    position = 0;
46
+    positionExt = 0;
47
+    positionExtPrev = 0;
48
+}
49
+
50
+int32_t encoder_pos(void)
51
+{
52
+    return positionExt;
53
+}
54
+
55
+void encoder_run(void) {
56
+    int8_t thisState = gpio_get(gpio_num[0]) | (gpio_get(gpio_num[1]) << 1);
57
+
58
+    if (oldState != thisState) {
59
+        position += KNOBDIR[thisState | (oldState << 2)];
60
+        oldState = thisState;
61
+
62
+        switch (ENCODER_MODE) {
63
+        case FOUR3:
64
+            if (thisState == LATCH3) {
65
+                // The hardware has 4 steps with a latch on the input state 3
66
+                positionExt = position >> 2;
67
+            }
68
+            break;
69
+
70
+        case FOUR0:
71
+            if (thisState == LATCH0) {
72
+                // The hardware has 4 steps with a latch on the input state 0
73
+                positionExt = position >> 2;
74
+            }
75
+            break;
76
+
77
+        case TWO03:
78
+            if ((thisState == LATCH0) || (thisState == LATCH3)) {
79
+                // The hardware has 2 steps with a latch on the input state 0 and 3
80
+                positionExt = position >> 1;
81
+            }
82
+            break;
83
+        }
84
+    }
85
+}

+ 39
- 0
src/lcd.c View File

@@ -0,0 +1,39 @@
1
+/*
2
+ * lcd.c
3
+ *
4
+ * Copyright (c) 2024 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include <stdio.h>
20
+#include <stdint.h>
21
+#include <string.h>
22
+#include "pico/stdlib.h"
23
+#include "hardware/i2c.h"
24
+
25
+#include "ssd1306.h"
26
+#include "lcd.h"
27
+
28
+static ssd1306_t disp;
29
+
30
+void lcd_init(void) {
31
+    i2c_init(i2c1, 400000);
32
+    gpio_set_function(0, GPIO_FUNC_I2C);
33
+    gpio_set_function(1, GPIO_FUNC_I2C);
34
+    gpio_pull_up(0);
35
+    gpio_pull_up(1);
36
+
37
+    disp.external_vcc = false;
38
+    ssd1306_init(&disp, 128, 64, 0x3C, i2c1);
39
+}

+ 39
- 0
src/led.c View File

@@ -0,0 +1,39 @@
1
+/*
2
+ * led.c
3
+ *
4
+ * Copyright (c) 2024 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include "pico/stdlib.h"
20
+
21
+#include "led.h"
22
+
23
+#define LED_COUNT 4
24
+
25
+static const uint gpio_num[LED_COUNT] = {
26
+    12, 13, 14, 15,
27
+};
28
+
29
+void led_init(void) {
30
+    for (uint i = 0; i < LED_COUNT; i++) {
31
+        gpio_init(gpio_num[i]);
32
+        gpio_set_dir(gpio_num[i], GPIO_IN);
33
+    }
34
+}
35
+
36
+void led_set(uint32_t i, bool v) {
37
+    i %= LED_COUNT;
38
+    gpio_put(i, v);
39
+}

+ 47
- 0
src/main.c View File

@@ -0,0 +1,47 @@
1
+/*
2
+ * main.c
3
+ *
4
+ * Copyright (c) 2024 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include <stdio.h>
20
+#include "pico/stdlib.h"
21
+#include "hardware/watchdog.h"
22
+
23
+#include "buttons.h"
24
+#include "encoder.h"
25
+#include "lcd.h"
26
+#include "sequence.h"
27
+#include "main.h"
28
+
29
+#define WATCHDOG_PERIOD_MS 100
30
+
31
+int main(void) {
32
+    watchdog_enable(WATCHDOG_PERIOD_MS, 1);
33
+    stdio_init_all();
34
+    buttons_init();
35
+    lcd_init();
36
+    sequence_init();
37
+    printf("init done\n");
38
+
39
+    while (1) {
40
+        watchdog_update();
41
+        buttons_run();
42
+        encoder_run();
43
+        sequence_run();
44
+    }
45
+
46
+    return 0;
47
+}

+ 70
- 0
src/sequence.c View File

@@ -0,0 +1,70 @@
1
+/*
2
+ * sequence.c
3
+ *
4
+ * Copyright (c) 2024 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include <stdio.h>
20
+#include "pico/stdlib.h"
21
+
22
+#include "led.h"
23
+#include "sequence.h"
24
+
25
+#define MAX_BEATS 32
26
+
27
+static uint32_t ms_per_beat = 500;
28
+static uint32_t beats = 16;
29
+static uint32_t last_t = 0;
30
+static uint32_t last_i = 0;
31
+
32
+static bool sequence[MAX_BEATS] = {0};
33
+
34
+void sequence_init(void) {
35
+    last_t = to_ms_since_boot(get_absolute_time());
36
+    last_i = 0;
37
+}
38
+
39
+void sequence_set_bpm(uint32_t new_bpm) {
40
+    ms_per_beat = 60000 / new_bpm;
41
+}
42
+
43
+void sequence_set_beats(uint32_t new_beats) {
44
+    beats = (new_beats <= MAX_BEATS) ? new_beats : MAX_BEATS;
45
+}
46
+
47
+void sequence_set(uint32_t beat, bool value) {
48
+    if (beat < MAX_BEATS) {
49
+        sequence[beat] = value;
50
+    }
51
+}
52
+
53
+void sequence_run(void) {
54
+    uint32_t now = to_ms_since_boot(get_absolute_time());
55
+
56
+    if ((last_t + ms_per_beat) >= now) {
57
+        uint32_t i = last_i + 1;
58
+        if (i >= beats) i = 0;
59
+
60
+        led_set(last_i, false);
61
+        led_set(i, true);
62
+
63
+        if (sequence[i]) {
64
+            // TODO trigger GPIO impulse
65
+        }
66
+
67
+        last_t = now;
68
+        last_i = i;
69
+    }
70
+}

Loading…
Cancel
Save