瀏覽代碼

machine now basically working

Thomas Buck 8 月之前
父節點
當前提交
ef07f43344
共有 8 個檔案被更改,包括 93 行新增21 行删除
  1. 1
    0
      CMakeLists.txt
  2. 4
    0
      README.md
  3. 5
    1
      include/sequence.h
  4. 4
    2
      include/ui.h
  5. 3
    0
      src/lcd.c
  6. 4
    0
      src/main.c
  7. 41
    15
      src/sequence.c
  8. 31
    3
      src/ui.c

+ 1
- 0
CMakeLists.txt 查看文件

@@ -53,6 +53,7 @@ target_compile_options(drumkit PUBLIC
53 53
     -Wextra
54 54
     -Werror
55 55
     -Wshadow
56
+    -O3
56 57
 )
57 58
 
58 59
 # suppress some warnings for borked 3rd party files in Pico SDK

+ 4
- 0
README.md 查看文件

@@ -1,5 +1,9 @@
1 1
 # Drumkit
2 2
 
3
+This is a simple drum machine / loopstation.
4
+It's made for three hand-wound solenoids mounted to a tambourine.
5
+It is controlled by a Raspberry Pi Pico.
6
+
3 7
 ## Quick Start
4 8
 
5 9
 Initialize your local repo and prepare the build:

+ 5
- 1
include/sequence.h 查看文件

@@ -36,7 +36,7 @@ enum channels {
36 36
 
37 37
 #define CH_GPIO_TIMINGS { 42, 42, 42 } // in milliseconds
38 38
 
39
-#define MAX_BEATS 32
39
+#define MAX_BEATS 128
40 40
 #define MAX_BANKS (MAX_BEATS / NUM_BTNS)
41 41
 
42 42
 void sequence_init(void);
@@ -44,6 +44,8 @@ void sequence_init(void);
44 44
 void sequence_set_bpm(uint32_t new_bpm);
45 45
 uint32_t sequence_get_bpm(void);
46 46
 
47
+uint32_t sequence_get_ms(void);
48
+
47 49
 void sequence_set_beats(uint32_t new_beats);
48 50
 uint32_t sequence_get_beats(void);
49 51
 
@@ -53,6 +55,8 @@ uint32_t sequence_get_bank(void);
53 55
 void sequence_handle_button_loopstation(enum buttons btn, bool rec);
54 56
 void sequence_handle_button_drummachine(enum buttons btn);
55 57
 
58
+void sequence_looptime(bool fin);
59
+
56 60
 void sequence_run(void);
57 61
 
58 62
 #endif // __SEQUENCE_H__

+ 4
- 2
include/ui.h 查看文件

@@ -22,8 +22,8 @@
22 22
 #include <stdint.h>
23 23
 
24 24
 enum ui_modes {
25
-    UI_BPM = 0,
26
-    UI_MODE,
25
+    UI_MODE = 0,
26
+    UI_BPM,
27 27
     UI_BANK,
28 28
     UI_LENGTH,
29 29
 
@@ -41,4 +41,6 @@ void ui_init(void);
41 41
 void ui_encoder(int32_t val);
42 42
 void ui_run(void);
43 43
 
44
+enum machine_modes ui_get_machinemode(void);
45
+
44 46
 #endif // __UI_H__

+ 3
- 0
src/lcd.c 查看文件

@@ -40,7 +40,10 @@ void lcd_init(void) {
40 40
 
41 41
     disp.external_vcc = false;
42 42
     ssd1306_init(&disp, LCD_WIDTH, LCD_HEIGHT, LCD_ADDR, LCD_I2C);
43
+
43 44
     ssd1306_clear(&disp);
45
+    ssd1306_draw_string(&disp, 0, 5, 5, "LARS");
46
+    ssd1306_show(&disp);
44 47
 }
45 48
 
46 49
 void lcd_draw(const char *mode, const char *val, const char *bat) {

+ 4
- 0
src/main.c 查看文件

@@ -49,6 +49,10 @@ int main(void) {
49 49
     encoder_init();
50 50
     lcd_init();
51 51
     led_init();
52
+
53
+    // show splash for a bit
54
+    sleep_ms(500);
55
+
52 56
     sequence_init();
53 57
     ui_init();
54 58
     printf("init done\n");

+ 41
- 15
src/sequence.c 查看文件

@@ -17,23 +17,28 @@
17 17
  */
18 18
 
19 19
 #include <stdio.h>
20
+#include <inttypes.h>
20 21
 #include "pico/stdlib.h"
21 22
 
22 23
 #include "led.h"
23 24
 #include "pulse.h"
25
+#include "ui.h"
24 26
 #include "sequence.h"
25 27
 
26 28
 static const uint32_t channel_times[NUM_CHANNELS] = CH_GPIO_TIMINGS;
27 29
 
28
-static uint32_t ms_per_beat = 500;
29
-static uint32_t beats = 16;
30
+static uint32_t ms_per_beat = 0;
31
+static uint32_t beats = MAX_BEATS;
30 32
 static uint32_t last_t = 0;
31 33
 static uint32_t last_i = 0;
32 34
 static uint32_t bank = 0;
35
+static uint32_t beattimer_start = 0;
33 36
 
34 37
 static enum channels sequence[MAX_BEATS] = {0};
35 38
 
36 39
 void sequence_init(void) {
40
+    ms_per_beat = 0;
41
+    beats = MAX_BEATS;
37 42
     last_t = to_ms_since_boot(get_absolute_time());
38 43
     last_i = 0;
39 44
 
@@ -43,11 +48,16 @@ void sequence_init(void) {
43 48
 }
44 49
 
45 50
 void sequence_set_bpm(uint32_t new_bpm) {
46
-    ms_per_beat = 60000 / new_bpm;
51
+    ms_per_beat = 60000 / new_bpm / beats;
52
+    printf("bpm now %"PRIu32" = %"PRIu32"ms\n", new_bpm, ms_per_beat);
47 53
 }
48 54
 
49 55
 uint32_t sequence_get_bpm(void) {
50
-    return 60000 / ms_per_beat;
56
+    return 60000 / (ms_per_beat * beats);
57
+}
58
+
59
+uint32_t sequence_get_ms(void) {
60
+    return ms_per_beat;
51 61
 }
52 62
 
53 63
 void sequence_set_beats(uint32_t new_beats) {
@@ -115,21 +125,19 @@ void sequence_handle_button_loopstation(enum buttons btn, bool rec) {
115 125
     }
116 126
 
117 127
     if (rec) {
118
-        uint32_t beat = 42; // TODO!!
119
-
120 128
         switch (btn) {
121 129
             case BTN_A: {
122
-                sequence_set(beat, CH_KICK, true);
130
+                sequence_set(last_i, CH_KICK, true);
123 131
                 break;
124 132
             }
125 133
 
126 134
             case BTN_B: {
127
-                sequence_set(beat, CH_SNARE, true);
135
+                sequence_set(last_i, CH_SNARE, true);
128 136
                 break;
129 137
             }
130 138
 
131 139
             case BTN_C: {
132
-                sequence_set(beat, CH_HIHAT, true);
140
+                sequence_set(last_i, CH_HIHAT, true);
133 141
                 break;
134 142
             }
135 143
 
@@ -171,25 +179,43 @@ void sequence_handle_button_drummachine(enum buttons btn) {
171 179
     }
172 180
 }
173 181
 
182
+void sequence_looptime(bool fin) {
183
+    if (!fin) {
184
+        beattimer_start = to_ms_since_boot(get_absolute_time());
185
+    } else {
186
+        if (ms_per_beat == 0) {
187
+            uint32_t now = to_ms_since_boot(get_absolute_time());
188
+            uint32_t diff = now - beattimer_start;
189
+            ms_per_beat = diff / beats;
190
+            printf("looptime: diff=%"PRIu32"ms per_beat=%"PRIu32"ms\n", diff, ms_per_beat);
191
+        }
192
+    }
193
+}
194
+
174 195
 void sequence_run(void) {
175
-    /*
176 196
     uint32_t now = to_ms_since_boot(get_absolute_time());
177 197
 
178
-    if ((last_t + ms_per_beat) >= now) {
198
+    if ((ms_per_beat > 0) && (now >= (last_t + ms_per_beat))) {
199
+        //printf("trigger\n");
200
+
179 201
         uint32_t i = last_i + 1;
180 202
         if (i >= beats) i = 0;
181 203
 
182
-        led_set(last_i, false);
183
-        led_set(i, true);
204
+        if (ui_get_machinemode() == MODE_DRUMMACHINE) {
205
+            led_set(last_i, false);
206
+            led_set(i, true);
207
+        }
184 208
 
185 209
         for (uint ch = 0; ch < NUM_CHANNELS; ch++) {
186 210
             if (sequence[i] & (1 << ch)) {
187
-                pulse_trigger_out(i, channel_times[ch]);
211
+                pulse_trigger_out(ch, channel_times[ch]);
212
+                if (ui_get_machinemode() == MODE_LOOPSTATION) {
213
+                    pulse_trigger_led(ch, channel_times[ch]);
214
+                }
188 215
             }
189 216
         }
190 217
 
191 218
         last_t = now;
192 219
         last_i = i;
193 220
     }
194
-    */
195 221
 }

+ 31
- 3
src/ui.c 查看文件

@@ -33,6 +33,10 @@ static enum ui_modes ui_mode = 0;
33 33
 static enum machine_modes machine_mode = 0;
34 34
 static uint32_t last_redraw = 0;
35 35
 
36
+enum machine_modes ui_get_machinemode(void) {
37
+    return machine_mode;
38
+}
39
+
36 40
 static void ui_redraw(void) {
37 41
     char mode[64] = {0};
38 42
     char val[64] = {0};
@@ -46,7 +50,11 @@ static void ui_redraw(void) {
46 50
         }
47 51
 
48 52
         case UI_MODE: {
49
-            snprintf(mode, sizeof(mode) - 1, "Mode:");
53
+            if ((machine_mode == MODE_LOOPSTATION) && (sequence_get_ms() != 0)) {
54
+                snprintf(mode, sizeof(mode) - 1, "Mode: %"PRIu32"ms", sequence_get_ms());
55
+            }else {
56
+                snprintf(mode, sizeof(mode) - 1, "Mode:");
57
+            }
50 58
             switch (machine_mode) {
51 59
                 case MODE_LOOPSTATION: {
52 60
                     snprintf(val, sizeof(val) - 1, "Loop");
@@ -59,7 +67,7 @@ static void ui_redraw(void) {
59 67
                 }
60 68
 
61 69
                 default: {
62
-                    printf("%s: invalid mode: %d\n", __func__, machine_mode);
70
+                    printf("%s: invalid machine mode: %d\n", __func__, machine_mode);
63 71
                     machine_mode = 0;
64 72
                     ui_redraw();
65 73
                     return;
@@ -105,6 +113,7 @@ static void ui_buttons_loopstation(enum buttons btn, bool val) {
105 113
 
106 114
         case BTN_REC: {
107 115
             rec_held_down = val;
116
+            sequence_looptime(!val);
108 117
             break;
109 118
         }
110 119
 
@@ -139,6 +148,13 @@ static void ui_buttons(enum buttons btn, bool val) {
139 148
         case BTN_CLICK: {
140 149
             if (val) {
141 150
                 ui_mode = (ui_mode + 1) % UI_NUM_MODES;
151
+
152
+                // allow other ui mdoes only in drumkit mode
153
+                if (machine_mode == MODE_LOOPSTATION)
154
+                {
155
+                    ui_mode = 0;
156
+                }
157
+
142 158
                 ui_redraw();
143 159
             }
144 160
             break;
@@ -180,7 +196,19 @@ void ui_encoder(int32_t val) {
180 196
         }
181 197
 
182 198
         case UI_MODE: {
183
-            machine_mode = (machine_mode + val) % MACHINE_NUM_MODES;
199
+            int32_t tmp = machine_mode + val;
200
+            while (tmp < 0) {
201
+                tmp += MACHINE_NUM_MODES;
202
+            }
203
+            while (tmp >= MACHINE_NUM_MODES) {
204
+                tmp -= MACHINE_NUM_MODES;
205
+            }
206
+            machine_mode = tmp;
207
+
208
+            printf("mode add %"PRIi32" now %d\n", val, machine_mode);
209
+
210
+            // reset sequence
211
+            sequence_init();
184 212
             break;
185 213
         }
186 214
 

Loading…
取消
儲存