Browse Source

machine now basically working

Thomas Buck 7 months ago
parent
commit
ef07f43344
8 changed files with 93 additions and 21 deletions
  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 View File

53
     -Wextra
53
     -Wextra
54
     -Werror
54
     -Werror
55
     -Wshadow
55
     -Wshadow
56
+    -O3
56
 )
57
 )
57
 
58
 
58
 # suppress some warnings for borked 3rd party files in Pico SDK
59
 # suppress some warnings for borked 3rd party files in Pico SDK

+ 4
- 0
README.md View File

1
 # Drumkit
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
 ## Quick Start
7
 ## Quick Start
4
 
8
 
5
 Initialize your local repo and prepare the build:
9
 Initialize your local repo and prepare the build:

+ 5
- 1
include/sequence.h View File

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

+ 4
- 2
include/ui.h View File

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

+ 3
- 0
src/lcd.c View File

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

+ 4
- 0
src/main.c View File

49
     encoder_init();
49
     encoder_init();
50
     lcd_init();
50
     lcd_init();
51
     led_init();
51
     led_init();
52
+
53
+    // show splash for a bit
54
+    sleep_ms(500);
55
+
52
     sequence_init();
56
     sequence_init();
53
     ui_init();
57
     ui_init();
54
     printf("init done\n");
58
     printf("init done\n");

+ 41
- 15
src/sequence.c View File

17
  */
17
  */
18
 
18
 
19
 #include <stdio.h>
19
 #include <stdio.h>
20
+#include <inttypes.h>
20
 #include "pico/stdlib.h"
21
 #include "pico/stdlib.h"
21
 
22
 
22
 #include "led.h"
23
 #include "led.h"
23
 #include "pulse.h"
24
 #include "pulse.h"
25
+#include "ui.h"
24
 #include "sequence.h"
26
 #include "sequence.h"
25
 
27
 
26
 static const uint32_t channel_times[NUM_CHANNELS] = CH_GPIO_TIMINGS;
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
 static uint32_t last_t = 0;
32
 static uint32_t last_t = 0;
31
 static uint32_t last_i = 0;
33
 static uint32_t last_i = 0;
32
 static uint32_t bank = 0;
34
 static uint32_t bank = 0;
35
+static uint32_t beattimer_start = 0;
33
 
36
 
34
 static enum channels sequence[MAX_BEATS] = {0};
37
 static enum channels sequence[MAX_BEATS] = {0};
35
 
38
 
36
 void sequence_init(void) {
39
 void sequence_init(void) {
40
+    ms_per_beat = 0;
41
+    beats = MAX_BEATS;
37
     last_t = to_ms_since_boot(get_absolute_time());
42
     last_t = to_ms_since_boot(get_absolute_time());
38
     last_i = 0;
43
     last_i = 0;
39
 
44
 
43
 }
48
 }
44
 
49
 
45
 void sequence_set_bpm(uint32_t new_bpm) {
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
 uint32_t sequence_get_bpm(void) {
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
 void sequence_set_beats(uint32_t new_beats) {
63
 void sequence_set_beats(uint32_t new_beats) {
115
     }
125
     }
116
 
126
 
117
     if (rec) {
127
     if (rec) {
118
-        uint32_t beat = 42; // TODO!!
119
-
120
         switch (btn) {
128
         switch (btn) {
121
             case BTN_A: {
129
             case BTN_A: {
122
-                sequence_set(beat, CH_KICK, true);
130
+                sequence_set(last_i, CH_KICK, true);
123
                 break;
131
                 break;
124
             }
132
             }
125
 
133
 
126
             case BTN_B: {
134
             case BTN_B: {
127
-                sequence_set(beat, CH_SNARE, true);
135
+                sequence_set(last_i, CH_SNARE, true);
128
                 break;
136
                 break;
129
             }
137
             }
130
 
138
 
131
             case BTN_C: {
139
             case BTN_C: {
132
-                sequence_set(beat, CH_HIHAT, true);
140
+                sequence_set(last_i, CH_HIHAT, true);
133
                 break;
141
                 break;
134
             }
142
             }
135
 
143
 
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
 void sequence_run(void) {
195
 void sequence_run(void) {
175
-    /*
176
     uint32_t now = to_ms_since_boot(get_absolute_time());
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
         uint32_t i = last_i + 1;
201
         uint32_t i = last_i + 1;
180
         if (i >= beats) i = 0;
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
         for (uint ch = 0; ch < NUM_CHANNELS; ch++) {
209
         for (uint ch = 0; ch < NUM_CHANNELS; ch++) {
186
             if (sequence[i] & (1 << ch)) {
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
         last_t = now;
218
         last_t = now;
192
         last_i = i;
219
         last_i = i;
193
     }
220
     }
194
-    */
195
 }
221
 }

+ 31
- 3
src/ui.c View File

33
 static enum machine_modes machine_mode = 0;
33
 static enum machine_modes machine_mode = 0;
34
 static uint32_t last_redraw = 0;
34
 static uint32_t last_redraw = 0;
35
 
35
 
36
+enum machine_modes ui_get_machinemode(void) {
37
+    return machine_mode;
38
+}
39
+
36
 static void ui_redraw(void) {
40
 static void ui_redraw(void) {
37
     char mode[64] = {0};
41
     char mode[64] = {0};
38
     char val[64] = {0};
42
     char val[64] = {0};
46
         }
50
         }
47
 
51
 
48
         case UI_MODE: {
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
             switch (machine_mode) {
58
             switch (machine_mode) {
51
                 case MODE_LOOPSTATION: {
59
                 case MODE_LOOPSTATION: {
52
                     snprintf(val, sizeof(val) - 1, "Loop");
60
                     snprintf(val, sizeof(val) - 1, "Loop");
59
                 }
67
                 }
60
 
68
 
61
                 default: {
69
                 default: {
62
-                    printf("%s: invalid mode: %d\n", __func__, machine_mode);
70
+                    printf("%s: invalid machine mode: %d\n", __func__, machine_mode);
63
                     machine_mode = 0;
71
                     machine_mode = 0;
64
                     ui_redraw();
72
                     ui_redraw();
65
                     return;
73
                     return;
105
 
113
 
106
         case BTN_REC: {
114
         case BTN_REC: {
107
             rec_held_down = val;
115
             rec_held_down = val;
116
+            sequence_looptime(!val);
108
             break;
117
             break;
109
         }
118
         }
110
 
119
 
139
         case BTN_CLICK: {
148
         case BTN_CLICK: {
140
             if (val) {
149
             if (val) {
141
                 ui_mode = (ui_mode + 1) % UI_NUM_MODES;
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
                 ui_redraw();
158
                 ui_redraw();
143
             }
159
             }
144
             break;
160
             break;
180
         }
196
         }
181
 
197
 
182
         case UI_MODE: {
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
             break;
212
             break;
185
         }
213
         }
186
 
214
 

Loading…
Cancel
Save