Browse Source

Merge branch 'feature_models' of thomas/drumkit into master

Thomas B 2 months ago
parent
commit
ecc7c9c212
20 changed files with 324 additions and 30 deletions
  1. 71
    0
      3dprint/actuator.scad
  2. 52
    0
      3dprint/beam.scad
  3. BIN
      3dprint/beam.stl
  4. 1
    0
      3dprint/enclosure.scad
  5. 1
    2
      3dprint/tamb_mount.json
  6. 10
    11
      3dprint/tamb_mount.scad
  7. 1
    0
      CMakeLists.txt
  8. 1
    1
      README.md
  9. 25
    0
      include/adc.h
  10. 0
    1
      include/buttons.h
  11. 0
    1
      include/encoder.h
  12. 1
    0
      include/lcd.h
  13. 12
    0
      include/sequence.h
  14. 1
    0
      include/ui.h
  15. 47
    0
      src/adc.c
  16. 4
    1
      src/encoder.c
  17. 10
    0
      src/lcd.c
  18. 3
    0
      src/main.c
  19. 26
    1
      src/sequence.c
  20. 58
    12
      src/ui.c

+ 71
- 0
3dprint/actuator.scad View File

1
+$fa=1/1;
2
+$fs=1/2;
3
+bissl=1/2;
4
+part="spool";//[spool,cap,hammer,all]
5
+total_length=50;
6
+wall=0.8;
7
+air=0.5;
8
+copper_height=5;
9
+thick_wall=2*wall; //can be specified
10
+iron_d=4;
11
+iron_h=total_length/3; //can be changed, but this seems optimal
12
+spool_h=iron_h; //according to theory, optimum is a little more
13
+iron_travel=iron_h; //may be smaller with heavy beaters or returning springs
14
+extra_hold=iron_h/3;
15
+spool_id=iron_d+2*air;
16
+spool_od=spool_id+2*wall;
17
+cap_od=spool_od+2*copper_height;
18
+slit=15;
19
+hole=3;
20
+hammer_flat=true;
21
+module spool() {
22
+  difference() {
23
+    union() {
24
+      cylinder(d1=spool_od,d2=cap_od,h=thick_wall+iron_travel);
25
+      translate([0,0,iron_travel+thick_wall]) cylinder(d=spool_od,h=spool_h+extra_hold);
26
+    }
27
+    translate([0,0,thick_wall]) cylinder(d=spool_id,h=spool_h+iron_h+bissl+extra_hold);
28
+  }
29
+}
30
+module cap() {
31
+difference() {
32
+union() {
33
+cylinder(d=cap_od,h=thick_wall);
34
+translate([0,0,thick_wall])cylinder(d=spool_od+2*wall+2*air,h=extra_hold);
35
+translate([-cap_od/2,0,0])cube([cap_od,cap_od/2,thick_wall]);
36
+translate([-cap_od/2,cap_od/2,0])cube([cap_od,thick_wall,2*thick_wall+slit]);
37
+translate([-thick_wall/2,0,0])cube([thick_wall,cap_od/2,extra_hold+thick_wall]);
38
+}
39
+translate([0,0,-bissl])cylinder(d=spool_id,h=extra_hold+thick_wall+2*bissl);
40
+cylinder(d=spool_od+2*air,h=extra_hold);
41
+hull() {
42
+translate([cap_od/2-thick_wall-hole/2,cap_od/2+thick_wall/2,2*thick_wall+hole/2])rotate([90,0,0])cylinder (d=hole, h=thick_wall+bissl,center=true);
43
+translate([cap_od/2-thick_wall-hole/2,cap_od/2+thick_wall/2,slit])rotate([90,0,0])cylinder (d=hole, h=thick_wall+bissl,center=true);
44
+}
45
+hull() {
46
+translate([-cap_od/2+thick_wall+hole/2,cap_od/2+thick_wall/2,2*thick_wall+hole/2])rotate([90,0,0])cylinder (d=hole, h=thick_wall+bissl,center=true);
47
+translate([-cap_od/2+thick_wall+hole/2,cap_od/2+thick_wall/2,slit])rotate([90,0,0])cylinder (d=hole, h=thick_wall+bissl,center=true);
48
+}
49
+}
50
+}
51
+echo (cap_od-thick_wall*2-hole);
52
+module hammer() {
53
+if (hammer_flat) {
54
+cylinder(d=cap_od-2*air,h=thick_wall);
55
+translate([0,0,thick_wall]) cylinder(d1=cap_od-2*air,d2=iron_d,h=cap_od/2-iron_d/2-air/2);
56
+}
57
+else {
58
+cylinder(d2=cap_od/2,d1=iron_d,h=cap_od/4-iron_d/4);
59
+translate([0,0,cap_od/4-iron_d/4])cylinder(d=cap_od/2,h=thick_wall);
60
+translate([0,0,cap_od/4-iron_d/4+thick_wall]) cylinder(d1=cap_od/2,d2=iron_d,h=cap_od/4-iron_d/4);
61
+}
62
+translate([0,0,thick_wall+cap_od/2-iron_d/2-air/2]) cylinder(d=iron_d,h=1.5*iron_h);
63
+}
64
+if (part=="all") {
65
+spool();
66
+translate([0,0,spool_h+iron_h+bissl+air+thick_wall])cap();
67
+translate([0,0,total_length])mirror([0,0,1])hammer();
68
+}
69
+if (part=="spool") spool();
70
+if (part=="cap") cap();
71
+if (part=="hammer") hammer();

+ 52
- 0
3dprint/beam.scad View File

1
+$fa=1/1;
2
+$fs=1/2;
3
+bissl=1/100;
4
+wall=1.6;//twice nozzle diameter is fine, walls of triangles
5
+hole=3; //hole for mounting thread inserts
6
+hd=10; //horizontal distance between mounting points, depends on mounting hole distance in the actuator
7
+height=40; //dimension of the beam in the direction of tambourine depth
8
+vd=height-wall; //vertical distance between mounting holes
9
+segments=14; //number of mounting points, defines the beam length
10
+radius=1; //rounding of inner corners
11
+thickness=2*wall+hole; //thickness of the beam, keep some material to properly hold the threaded insert on the side
12
+offset=wall/2+hole/2;
13
+difference() {
14
+  linear_extrude(thickness, convexity=4) difference() {
15
+    offset(r=-radius)offset(r=radius)union() {
16
+      for (i=[0:hd:hd*(segments-1)]) translate ([i,0]) {
17
+        for (tr=[[[hd,0],[0,0]],[[-hd/2,vd],[0,0]],[[hd/2,vd],[0,0]],[[hd/2,vd],[-hd/2,vd]]]) hull() { //diagonals
18
+          translate(tr[0])circle(d=wall);
19
+          translate(tr[1]) circle(d=wall);
20
+        }
21
+        for (tr=[[hd/2,vd-offset],[-hd/2,vd-offset],[hd,offset],[0,offset]]) translate(tr)circle(d=2*wall+hole); //big circles
22
+      }
23
+    
24
+      //left vertical wall, not generated by the loop
25
+      for (tr=[[[-hd/2-offset,0],[0,0]],[[-hd/2-offset,0],[-hd/2-offset,vd]],[[-hd/2-offset,vd],[-hd/2,vd]]]) hull() {
26
+        translate(tr[0])circle(d=wall);
27
+        translate(tr[1]) circle(d=wall);
28
+      }
29
+
30
+      //solid triangle to jhold threaded inserts
31
+      hull() for (tr=[[0,0],[-hd/2-offset,0],[-hd/2-offset,vd],[-hd/2,vd]]) translate(tr) circle(d=wall); 
32
+
33
+      //right vertical wall, not generated by the loop
34
+      for (tr=[[[hd*segments+offset,0],[0,0]],
35
+               [[hd*segments+offset,0],[hd*segments+offset,vd]],
36
+               [[hd*segments+offset,vd],[hd*(segments-0.5),vd]],
37
+               [[hd*segments,0],[hd*(segments-0.5),vd]]]) 
38
+        hull() {
39
+          translate(tr[0])circle(d=wall);
40
+          translate(tr[1]) circle(d=wall);
41
+        }
42
+    }
43
+    for (i=[0:segments]) {
44
+      translate([i*hd,offset]) circle(d=hole);
45
+      translate([(i-0.5)*hd,vd-offset]) circle(d=hole);
46
+    }
47
+  }
48
+  //mounting holes for threaded inserts, three just in case, it's better to use the middle one
49
+  translate([-hd/2-offset-wall/2,height/4-wall,thickness/2])rotate([0,90,0])cylinder(d=hole,h=hd-wall);
50
+  translate([-hd/2-offset-wall/2,height/2-wall/2,thickness/2])rotate([0,90,0])cylinder(d=hole,h=hd-wall);
51
+  translate([-hd/2-offset-wall/2,height*3/4,thickness/2])rotate([0,90,0])cylinder(d=hole,h=hd-wall);
52
+}

BIN
3dprint/beam.stl View File


+ 1
- 0
3dprint/enclosure.scad View File

1
+part="bottom";//[bottom,top]

+ 1
- 2
3dprint/tamb_mount.json View File

9
             "id_tamb": "239",
9
             "id_tamb": "239",
10
             "lip": "3",
10
             "lip": "3",
11
             "od_tamb": "251",
11
             "od_tamb": "251",
12
-            "part": "outer",
13
-            "wall": "1.6000000000000001"
12
+            "part": "outer"
14
         }
13
         }
15
     }
14
     }
16
 }
15
 }

+ 10
- 11
3dprint/tamb_mount.scad View File

2
 $fs=1/2;
2
 $fs=1/2;
3
 bissl=1/100;
3
 bissl=1/100;
4
 part="inner";//[inner,outer,all_visualize]
4
 part="inner";//[inner,outer,all_visualize]
5
-od_tamb=251;
6
-id_tamb=239;
7
-wall_tamb=(od_tamb-id_tamb)/2;
8
-hole_tamb=23;
9
-lip=3;
10
-air=1;
11
-hole=3;
12
-wall=1.6;
13
-beam_width=7;
5
+od_tamb=251;//tambourine rim outer diameter
6
+id_tamb=239;//tambourine rim inner diameter
7
+wall_tamb=(od_tamb-id_tamb)/2; //tambourine wall
8
+hole_tamb=23; //holding hole in the rim
9
+lip=3; //extra plastic that hols to the hole
10
+air=1; //wiggle room
11
+hole=3; //diameter for screw hole
12
+beam_width=7; //slit in inner part of mount to hod the beam
13
+wall=1.6;//thinnest part in the mount, namely the slit to tune the beam mounting height
14
 module inner_mount() {
14
 module inner_mount() {
15
   difference() {
15
   difference() {
16
     union() {
16
     union() {
30
     translate([-beam_width/2-air/2,-hole_tamb/2-lip,-bissl]) cube([beam_width+air,hole_tamb+2*lip,lip]);
30
     translate([-beam_width/2-air/2,-hole_tamb/2-lip,-bissl]) cube([beam_width+air,hole_tamb+2*lip,lip]);
31
   }
31
   }
32
 }
32
 }
33
-
34
 module outer_mount() {
33
 module outer_mount() {
35
   difference() {
34
   difference() {
36
     union() {
35
     union() {
54
 if (part=="all_visualize") {
53
 if (part=="all_visualize") {
55
   inner_mount();
54
   inner_mount();
56
   translate([0,0,wall_tamb+3*lip])rotate([180,0,0])outer_mount();
55
   translate([0,0,wall_tamb+3*lip])rotate([180,0,0])outer_mount();
57
-  }
56
+}

+ 1
- 0
CMakeLists.txt View File

30
 add_executable(drumkit)
30
 add_executable(drumkit)
31
 
31
 
32
 target_sources(drumkit PUBLIC
32
 target_sources(drumkit PUBLIC
33
+    src/adc.c
33
     src/buttons.c
34
     src/buttons.c
34
     src/encoder.c
35
     src/encoder.c
35
     src/lcd.c
36
     src/lcd.c

+ 1
- 1
README.md View File

53
 
53
 
54
 The code in `src/encoder.c` is derived from [mathertel/RotaryEncoder](https://github.com/mathertel/RotaryEncoder) and therefore licensed as BSD 3-clause.
54
 The code in `src/encoder.c` is derived from [mathertel/RotaryEncoder](https://github.com/mathertel/RotaryEncoder) and therefore licensed as BSD 3-clause.
55
 
55
 
56
-The PCB design uses `Mini360_step_down_converter` library from [rayvburn/KiCad](https://github.com/rayvburn/KiCad/tree/master/Mini360_step_down_converter).
56
+~~The PCB design uses `Mini360_step_down_converter` library from [rayvburn/KiCad](https://github.com/rayvburn/KiCad/tree/master/Mini360_step_down_converter).~~
57
 
57
 
58
     This program is free software: you can redistribute it and/or modify
58
     This program is free software: you can redistribute it and/or modify
59
     it under the terms of the GNU General Public License as published by
59
     it under the terms of the GNU General Public License as published by

+ 25
- 0
include/adc.h View File

1
+/*
2
+ * adc.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 __ADC_H__
20
+#define __ADC_H__
21
+
22
+void bat_init(void);
23
+float bat_get(void);
24
+
25
+#endif // __ADC_H__

+ 0
- 1
include/buttons.h View File

35
 void buttons_run(void);
35
 void buttons_run(void);
36
 
36
 
37
 #endif // __BUTTONS_H__
37
 #endif // __BUTTONS_H__
38
-

+ 0
- 1
include/encoder.h View File

26
 void encoder_run(void);
26
 void encoder_run(void);
27
 
27
 
28
 #endif // __ENCODER_H__
28
 #endif // __ENCODER_H__
29
-

+ 1
- 0
include/lcd.h View File

23
 #define LCD_HEIGHT 64
23
 #define LCD_HEIGHT 64
24
 
24
 
25
 void lcd_init(void);
25
 void lcd_init(void);
26
+void lcd_draw(const char *mode, const char *val, const char *bat);
26
 
27
 
27
 #endif // __LCD_H__
28
 #endif // __LCD_H__

+ 12
- 0
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
40
+#define MAX_BANKS (MAX_BEATS / NUM_BTNS)
41
+
39
 void sequence_init(void);
42
 void sequence_init(void);
43
+
40
 void sequence_set_bpm(uint32_t new_bpm);
44
 void sequence_set_bpm(uint32_t new_bpm);
45
+uint32_t sequence_get_bpm(void);
46
+
41
 void sequence_set_beats(uint32_t new_beats);
47
 void sequence_set_beats(uint32_t new_beats);
48
+uint32_t sequence_get_beats(void);
49
+
50
+void sequence_set_bank(uint32_t new_bank);
51
+uint32_t sequence_get_bank(void);
52
+
42
 void sequence_handle_button_loopstation(enum buttons btn, bool rec);
53
 void sequence_handle_button_loopstation(enum buttons btn, bool rec);
43
 void sequence_handle_button_drummachine(enum buttons btn);
54
 void sequence_handle_button_drummachine(enum buttons btn);
55
+
44
 void sequence_run(void);
56
 void sequence_run(void);
45
 
57
 
46
 #endif // __SEQUENCE_H__
58
 #endif // __SEQUENCE_H__

+ 1
- 0
include/ui.h View File

39
 
39
 
40
 void ui_init(void);
40
 void ui_init(void);
41
 void ui_encoder(int32_t val);
41
 void ui_encoder(int32_t val);
42
+void ui_run(void);
42
 
43
 
43
 #endif // __UI_H__
44
 #endif // __UI_H__

+ 47
- 0
src/adc.c View File

1
+/*
2
+ * adc.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/adc.h"
22
+
23
+#include "adc.h"
24
+
25
+#define ADC_NUM 2
26
+#define ADC_PIN (26 + ADC_NUM)
27
+
28
+#define ADC_VREF 3.3
29
+#define ADC_RANGE (1 << 12)
30
+#define ADC_CONVERT (ADC_VREF / (ADC_RANGE - 1))
31
+
32
+#define BAT_R1 10000.0f
33
+#define BAT_R2 18000.0f
34
+
35
+void bat_init(void) {
36
+    adc_init();
37
+    adc_gpio_init( ADC_PIN);
38
+    adc_select_input( ADC_NUM);
39
+}
40
+
41
+float bat_get(void) {
42
+    float v_adc = adc_read() * ADC_CONVERT;
43
+
44
+    // Vadc = Vbat * R2 / (R1 + R2)
45
+    float v_bat = v_adc / (BAT_R2 / (BAT_R1 + BAT_R2));
46
+    return v_bat;
47
+}

+ 4
- 1
src/encoder.c View File

22
 #define FOUR0 2 // 4 steps, Latch at position 0 (reverse wirings)
22
 #define FOUR0 2 // 4 steps, Latch at position 0 (reverse wirings)
23
 #define TWO03 3 // 2 steps, Latch at position 0 and 3
23
 #define TWO03 3 // 2 steps, Latch at position 0 and 3
24
 
24
 
25
-#define ENCODER_MODE TWO03
25
+#define ENCODER_MODE FOUR3
26
 
26
 
27
 static const uint gpio_num[2] = {
27
 static const uint gpio_num[2] = {
28
     17, 18
28
     17, 18
70
             if (thisState == LATCH3) {
70
             if (thisState == LATCH3) {
71
                 // The hardware has 4 steps with a latch on the input state 3
71
                 // The hardware has 4 steps with a latch on the input state 3
72
                 positionExt = position >> 2;
72
                 positionExt = position >> 2;
73
+                positionExt = -positionExt;
73
             }
74
             }
74
             break;
75
             break;
75
 
76
 
77
             if (thisState == LATCH0) {
78
             if (thisState == LATCH0) {
78
                 // The hardware has 4 steps with a latch on the input state 0
79
                 // The hardware has 4 steps with a latch on the input state 0
79
                 positionExt = position >> 2;
80
                 positionExt = position >> 2;
81
+                positionExt = -positionExt;
80
             }
82
             }
81
             break;
83
             break;
82
 
84
 
84
             if ((thisState == LATCH0) || (thisState == LATCH3)) {
86
             if ((thisState == LATCH0) || (thisState == LATCH3)) {
85
                 // The hardware has 2 steps with a latch on the input state 0 and 3
87
                 // The hardware has 2 steps with a latch on the input state 0 and 3
86
                 positionExt = position >> 1;
88
                 positionExt = position >> 1;
89
+                positionExt = -positionExt;
87
             }
90
             }
88
             break;
91
             break;
89
         }
92
         }

+ 10
- 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
+    ssd1306_clear(&disp);
44
+}
45
+
46
+void lcd_draw(const char *mode, const char *val, const char *bat) {
47
+    ssd1306_clear(&disp);
48
+    ssd1306_draw_string(&disp, 0, 0, 2, mode);
49
+    ssd1306_draw_string(&disp, 0, 20, 4, val);
50
+    ssd1306_draw_string(&disp, 0, LCD_HEIGHT - 1 - 10, 1, bat);
51
+
52
+    ssd1306_show(&disp);
43
 }
53
 }

+ 3
- 0
src/main.c View File

20
 #include "pico/stdlib.h"
20
 #include "pico/stdlib.h"
21
 #include "hardware/watchdog.h"
21
 #include "hardware/watchdog.h"
22
 
22
 
23
+#include "adc.h"
23
 #include "buttons.h"
24
 #include "buttons.h"
24
 #include "encoder.h"
25
 #include "encoder.h"
25
 #include "lcd.h"
26
 #include "lcd.h"
34
 int main(void) {
35
 int main(void) {
35
     watchdog_enable(WATCHDOG_PERIOD_MS, 1);
36
     watchdog_enable(WATCHDOG_PERIOD_MS, 1);
36
     stdio_init_all();
37
     stdio_init_all();
38
+    bat_init();
37
     buttons_init();
39
     buttons_init();
38
     encoder_init();
40
     encoder_init();
39
     lcd_init();
41
     lcd_init();
50
         encoder_run();
52
         encoder_run();
51
         sequence_run();
53
         sequence_run();
52
         pulse_run();
54
         pulse_run();
55
+        ui_run();
53
 
56
 
54
         int32_t epos = encoder_pos();
57
         int32_t epos = encoder_pos();
55
         if (epos != last_epos) {
58
         if (epos != last_epos) {

+ 26
- 1
src/sequence.c View File

23
 #include "pulse.h"
23
 #include "pulse.h"
24
 #include "sequence.h"
24
 #include "sequence.h"
25
 
25
 
26
-#define MAX_BEATS 32
27
 static const uint32_t channel_times[NUM_CHANNELS] = CH_GPIO_TIMINGS;
26
 static const uint32_t channel_times[NUM_CHANNELS] = CH_GPIO_TIMINGS;
28
 
27
 
29
 static uint32_t ms_per_beat = 500;
28
 static uint32_t ms_per_beat = 500;
30
 static uint32_t beats = 16;
29
 static uint32_t beats = 16;
31
 static uint32_t last_t = 0;
30
 static uint32_t last_t = 0;
32
 static uint32_t last_i = 0;
31
 static uint32_t last_i = 0;
32
+static uint32_t bank = 0;
33
 
33
 
34
 static enum channels sequence[MAX_BEATS] = {0};
34
 static enum channels sequence[MAX_BEATS] = {0};
35
 
35
 
46
     ms_per_beat = 60000 / new_bpm;
46
     ms_per_beat = 60000 / new_bpm;
47
 }
47
 }
48
 
48
 
49
+uint32_t sequence_get_bpm(void) {
50
+    return 60000 / ms_per_beat;
51
+}
52
+
49
 void sequence_set_beats(uint32_t new_beats) {
53
 void sequence_set_beats(uint32_t new_beats) {
50
     beats = (new_beats <= MAX_BEATS) ? new_beats : MAX_BEATS;
54
     beats = (new_beats <= MAX_BEATS) ? new_beats : MAX_BEATS;
55
+
56
+    uint32_t max_banks_currently = (beats + (NUM_BTNS - 1)) / NUM_BTNS;
57
+    bank = (bank < max_banks_currently) ? bank : max_banks_currently;
58
+}
59
+
60
+uint32_t sequence_get_beats(void) {
61
+    return beats;
62
+}
63
+
64
+void sequence_set_bank(uint32_t new_bank) {
65
+    uint32_t b = (new_bank < MAX_BANKS) ? new_bank : MAX_BANKS;
66
+
67
+    uint32_t max_banks_currently = (beats + (NUM_BTNS - 1)) / NUM_BTNS;
68
+    bank = (b < max_banks_currently) ? b : max_banks_currently;
69
+}
70
+
71
+uint32_t sequence_get_bank(void) {
72
+    return bank;
51
 }
73
 }
52
 
74
 
53
 static void sequence_set(uint32_t beat, enum channels ch, bool value) {
75
 static void sequence_set(uint32_t beat, enum channels ch, bool value) {
123
 
145
 
124
     switch (btn) {
146
     switch (btn) {
125
         case BTN_A: {
147
         case BTN_A: {
148
+            // TODO kick is wrong here
126
             bool val = !sequence_get(beat, CH_KICK);
149
             bool val = !sequence_get(beat, CH_KICK);
127
             sequence_set(beat, CH_KICK, val);
150
             sequence_set(beat, CH_KICK, val);
128
             break;
151
             break;
129
         }
152
         }
130
 
153
 
131
         case BTN_B: {
154
         case BTN_B: {
155
+            // TODO snare is wrong here
132
             bool val = !sequence_get(beat, CH_SNARE);
156
             bool val = !sequence_get(beat, CH_SNARE);
133
             sequence_set(beat, CH_SNARE, val);
157
             sequence_set(beat, CH_SNARE, val);
134
             break;
158
             break;
135
         }
159
         }
136
 
160
 
137
         case BTN_C: {
161
         case BTN_C: {
162
+            // TODO hihat is wrong here
138
             bool val = !sequence_get(beat, CH_HIHAT);
163
             bool val = !sequence_get(beat, CH_HIHAT);
139
             sequence_set(beat, CH_HIHAT, val);
164
             sequence_set(beat, CH_HIHAT, val);
140
             break;
165
             break;

+ 58
- 12
src/ui.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
 
23
+#include "adc.h"
22
 #include "buttons.h"
24
 #include "buttons.h"
25
+#include "lcd.h"
23
 #include "sequence.h"
26
 #include "sequence.h"
24
 #include "ui.h"
27
 #include "ui.h"
25
 
28
 
29
+#define REDRAW_MS 2000
30
+
26
 static bool rec_held_down = false;
31
 static bool rec_held_down = false;
27
 static enum ui_modes ui_mode = 0;
32
 static enum ui_modes ui_mode = 0;
28
 static enum machine_modes machine_mode = 0;
33
 static enum machine_modes machine_mode = 0;
34
+static uint32_t last_redraw = 0;
29
 
35
 
30
 static void ui_redraw(void) {
36
 static void ui_redraw(void) {
37
+    char mode[64] = {0};
38
+    char val[64] = {0};
39
+    char bat[64] = {0};
40
+
31
     switch (ui_mode) {
41
     switch (ui_mode) {
32
         case UI_BPM: {
42
         case UI_BPM: {
33
-            // TODO
43
+            snprintf(mode, sizeof(mode) - 1, "BPM:");
44
+            snprintf(val, sizeof(val) - 1, "%"PRIu32, sequence_get_bpm());
34
             break;
45
             break;
35
         }
46
         }
36
 
47
 
37
         case UI_MODE: {
48
         case UI_MODE: {
38
-            // TODO
49
+            snprintf(mode, sizeof(mode) - 1, "Mode:");
50
+            switch (machine_mode) {
51
+                case MODE_LOOPSTATION: {
52
+                    snprintf(val, sizeof(val) - 1, "Loop");
53
+                    break;
54
+                }
55
+
56
+                case MODE_DRUMMACHINE: {
57
+                    snprintf(val, sizeof(val) - 1, "Drum");
58
+                    break;
59
+                }
60
+
61
+                default: {
62
+                    printf("%s: invalid mode: %d\n", __func__, machine_mode);
63
+                    machine_mode = 0;
64
+                    ui_redraw();
65
+                    return;
66
+                }
67
+            }
39
             break;
68
             break;
40
         }
69
         }
41
 
70
 
42
         case UI_LENGTH: {
71
         case UI_LENGTH: {
43
-            // TODO
72
+            snprintf(mode, sizeof(mode) - 1, "Length:");
73
+            snprintf(val, sizeof(val) - 1, "%"PRIu32, sequence_get_beats());
44
             break;
74
             break;
45
         }
75
         }
46
 
76
 
47
         case UI_BANK: {
77
         case UI_BANK: {
48
-            // TODO
78
+            snprintf(mode, sizeof(mode) - 1, "Bank:");
79
+            snprintf(val, sizeof(val) - 1, "%"PRIu32, sequence_get_bank());
49
             break;
80
             break;
50
         }
81
         }
51
 
82
 
53
             printf("%s: invalid mode: %d\n", __func__, ui_mode);
84
             printf("%s: invalid mode: %d\n", __func__, ui_mode);
54
             ui_mode = 0;
85
             ui_mode = 0;
55
             ui_redraw();
86
             ui_redraw();
56
-            break;
87
+            return;
57
         }
88
         }
58
     }
89
     }
90
+
91
+    snprintf(bat, sizeof(bat) - 1, "Bat: %.2fV", bat_get());
92
+    lcd_draw(mode, val, bat);
59
 }
93
 }
60
 
94
 
61
 static void ui_buttons_loopstation(enum buttons btn, bool val) {
95
 static void ui_buttons_loopstation(enum buttons btn, bool val) {
103
 static void ui_buttons(enum buttons btn, bool val) {
137
 static void ui_buttons(enum buttons btn, bool val) {
104
     switch (btn) {
138
     switch (btn) {
105
         case BTN_CLICK: {
139
         case BTN_CLICK: {
106
-            ui_mode = (ui_mode + 1) % UI_NUM_MODES;
107
-            ui_redraw();
140
+            if (val) {
141
+                ui_mode = (ui_mode + 1) % UI_NUM_MODES;
142
+                ui_redraw();
143
+            }
108
             break;
144
             break;
109
         }
145
         }
110
 
146
 
139
 
175
 
140
     switch (ui_mode) {
176
     switch (ui_mode) {
141
         case UI_BPM: {
177
         case UI_BPM: {
142
-            // TODO
178
+            sequence_set_bpm(sequence_get_bpm() + val);
143
             break;
179
             break;
144
         }
180
         }
145
 
181
 
146
         case UI_MODE: {
182
         case UI_MODE: {
147
-            // TODO
183
+            machine_mode = (machine_mode + val) % MACHINE_NUM_MODES;
148
             break;
184
             break;
149
         }
185
         }
150
 
186
 
151
         case UI_LENGTH: {
187
         case UI_LENGTH: {
152
-            // TODO
188
+            sequence_set_beats(sequence_get_beats() + val);
153
             break;
189
             break;
154
         }
190
         }
155
 
191
 
156
         case UI_BANK: {
192
         case UI_BANK: {
157
-            // TODO
193
+            sequence_set_bank(sequence_get_bank() + val);
158
             break;
194
             break;
159
         }
195
         }
160
 
196
 
162
             printf("%s: invalid mode: %d\n", __func__, ui_mode);
198
             printf("%s: invalid mode: %d\n", __func__, ui_mode);
163
             ui_mode = 0;
199
             ui_mode = 0;
164
             ui_encoder(val);
200
             ui_encoder(val);
165
-            break;
201
+            return;
166
         }
202
         }
167
     }
203
     }
204
+
205
+    ui_redraw();
168
 }
206
 }
169
 
207
 
170
 void ui_init(void) {
208
 void ui_init(void) {
171
     buttons_callback(ui_buttons);
209
     buttons_callback(ui_buttons);
172
     ui_redraw();
210
     ui_redraw();
173
 }
211
 }
212
+
213
+void ui_run(void) {
214
+    uint32_t now = to_ms_since_boot(get_absolute_time());
215
+    if (now >= (last_redraw + REDRAW_MS)) {
216
+        ui_redraw();
217
+        last_redraw = now;
218
+    }
219
+}

Loading…
Cancel
Save