Skip to content

Commit c08689e

Browse files
committed
feat: re-write demo feature to allow for arbitary note trigger
1 parent 38f30d4 commit c08689e

File tree

4 files changed

+169
-74
lines changed

4 files changed

+169
-74
lines changed

src/comm/comm_demo.c

Lines changed: 90 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,43 @@
33
#include "log.h"
44
#include "scheduler.h"
55
#include "midi.h"
6+
#include "ring_buf.h"
67

78
#define programChange 0xC0
89
#define noteOnStatus 0x90
910
#define noteOffStatus 0x80
1011
#define noteKey 69
1112
#define noteVelocity 127
1213

13-
#define PROGRAM_INDEX 4
14-
#define NOTE_KEY_1_INDEX 6
15-
#define NOTE_ON_END_INDEX 7
16-
#define NOTE_KEY_2_INDEX 9
17-
#define NOTE_OFF_END_INDEX 10
18-
19-
#define NOTE_ON_WAIT 50
20-
#define NOTE_OFF_WAIT 2
21-
22-
static u8 cursor;
23-
static u16 wait;
2414
static bool enabled;
2515
static u8 pitch;
2616
static u8 program;
17+
static u16 prev_joy_state;
18+
static u16 repeat_timer;
19+
static u16 repeat_button;
2720

28-
u8 track[] = {
29-
// CC: show parameters on UI
30-
0xB0,
31-
CC_SHOW_PARAMETERS_ON_UI,
32-
0x7F,
33-
// Change program
34-
programChange,
35-
0,
36-
// Note on
37-
noteOnStatus,
38-
noteKey,
39-
noteVelocity,
40-
// Note off
41-
noteOffStatus,
42-
noteKey,
43-
noteVelocity,
44-
};
21+
#define REPEAT_DELAY 10
22+
#define INITIAL_DELAY 30
4523

4624
void comm_demo_init(void)
4725
{
4826
scheduler_addFrameHandler(comm_demo_vsync);
4927
JOY_init();
50-
cursor = 0;
51-
wait = 0;
5228
enabled = false;
5329
pitch = noteKey;
5430
program = 0;
31+
prev_joy_state = 0;
32+
repeat_timer = 0;
33+
repeat_button = 0;
34+
ring_buf_init();
35+
36+
ring_buf_write(0xB0);
37+
ring_buf_write(CC_SHOW_PARAMETERS_ON_UI);
38+
ring_buf_write(0x7F);
39+
40+
ring_buf_write(noteOnStatus);
41+
ring_buf_write(pitch);
42+
ring_buf_write(0x7F);
5543
}
5644

5745
bool comm_demo_is_present(void)
@@ -64,71 +52,113 @@ u8 comm_demo_read_ready(void)
6452
if (!enabled) {
6553
if (JOY_readJoypad(JOY_1) & BUTTON_A) {
6654
enabled = true;
55+
} else {
56+
return false;
6757
}
6858
}
69-
if (!enabled) {
70-
return false;
71-
}
72-
return wait == 0;
59+
return ring_buf_can_read();
7360
}
7461

7562
u8 comm_demo_read(void)
7663
{
77-
if (cursor == 0) {
78-
track[PROGRAM_INDEX] = program;
79-
track[NOTE_KEY_1_INDEX] = pitch;
80-
track[NOTE_KEY_2_INDEX] = pitch;
81-
log_info("Demo: Pitch=%d Prg=%d", pitch, program);
82-
}
83-
u8 data = track[cursor];
84-
cursor++;
85-
if (cursor == NOTE_ON_END_INDEX + 1) {
86-
wait = NOTE_ON_WAIT;
64+
u8 data;
65+
if (ring_buf_read(&data) == RING_BUF_OK) {
66+
return data;
67+
} else {
68+
return 0;
8769
}
88-
if (cursor == NOTE_OFF_END_INDEX + 1) {
89-
wait = NOTE_OFF_WAIT;
90-
cursor = 0;
91-
}
92-
return data;
9370
}
9471

95-
static void decrement_wait(void)
72+
static void send_note_off(u8 pitch)
9673
{
97-
if (wait != 0) {
98-
wait--;
99-
}
74+
ring_buf_write(noteOffStatus);
75+
ring_buf_write(pitch);
76+
ring_buf_write(0);
77+
}
78+
79+
static void send_note_on(u8 pitch)
80+
{
81+
ring_buf_write(noteOnStatus);
82+
ring_buf_write(pitch);
83+
ring_buf_write(noteVelocity);
10084
}
10185

102-
void comm_demo_vsync(u16 wait)
86+
static void send_program_change(u8 program)
10387
{
104-
decrement_wait();
88+
ring_buf_write(programChange);
89+
ring_buf_write(program);
90+
}
10591

92+
static bool should_repeat_button(u16 joy_state, u16 button_mask)
93+
{
94+
if (joy_state & button_mask) {
95+
if (repeat_button != button_mask) {
96+
repeat_button = button_mask;
97+
repeat_timer = 1;
98+
return true;
99+
} else {
100+
repeat_timer++;
101+
if (repeat_timer > INITIAL_DELAY
102+
&& (repeat_timer - INITIAL_DELAY) % REPEAT_DELAY == 0) {
103+
return true;
104+
}
105+
}
106+
} else if (repeat_button == button_mask) {
107+
repeat_button = 0;
108+
repeat_timer = 0;
109+
}
110+
return false;
111+
}
112+
113+
void comm_demo_vsync(u16 delta)
114+
{
106115
JOY_update();
107-
u16 curState = JOY_readJoypad(JOY_1);
108-
if (curState & BUTTON_UP) {
116+
117+
u16 joy_state = JOY_readJoypad(JOY_1);
118+
119+
if (should_repeat_button(joy_state, BUTTON_UP)) {
120+
send_note_off(pitch);
109121
pitch++;
110122
if (pitch > MAX_MIDI_PITCH) {
111123
pitch = MAX_MIDI_PITCH;
112124
}
125+
send_note_on(pitch);
113126
}
114-
if (curState & BUTTON_DOWN) {
127+
if (should_repeat_button(joy_state, BUTTON_DOWN)) {
128+
send_note_off(pitch);
115129
pitch--;
116130
if (pitch < MIN_MIDI_PITCH) {
117131
pitch = MIN_MIDI_PITCH;
118132
}
133+
send_note_on(pitch);
119134
}
120-
if (curState & BUTTON_RIGHT) {
135+
if (should_repeat_button(joy_state, BUTTON_RIGHT)) {
136+
send_note_off(pitch);
121137
program++;
122138
if (program > 0x7F) {
123139
program = 0x7F;
124140
}
141+
send_program_change(program);
142+
send_note_on(pitch);
125143
}
126-
if (curState & BUTTON_LEFT) {
144+
if (should_repeat_button(joy_state, BUTTON_LEFT)) {
145+
send_note_off(pitch);
127146
program--;
128147
if (program == 0xFF) {
129148
program = 0;
130149
}
150+
send_program_change(program);
151+
send_note_on(pitch);
131152
}
153+
if (should_repeat_button(joy_state, BUTTON_A)) {
154+
send_note_off(pitch);
155+
send_note_on(pitch);
156+
}
157+
if (should_repeat_button(joy_state, BUTTON_B)) {
158+
send_note_off(pitch);
159+
}
160+
161+
prev_joy_state = joy_state;
132162
}
133163

134164
u8 comm_demo_write_ready(void)

tests/unit/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ int main(void)
323323
comm_demo_test(test_comm_demo_decreases_pitch),
324324
comm_demo_test(test_comm_demo_increases_program),
325325
comm_demo_test(test_comm_demo_decreases_program),
326+
comm_demo_test(test_comm_demo_button_repeat_with_initial_delay),
326327

327328
comm_megawifi_test(test_comm_megawifi_reads_midi_message),
328329
comm_megawifi_test(test_comm_megawifi_logs_if_buffer_full),

tests/unit/test_comm_demo.c

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ static void vsync_call(u16 buttonPressed)
4444
__real_comm_demo_vsync();
4545
}
4646

47+
static void vsync_call_multiple(u16 buttonPressed, int times)
48+
{
49+
for (int i = 0; i < times; i++) {
50+
expect_function_call(__wrap_JOY_update);
51+
will_return(__wrap_JOY_readJoypad, buttonPressed);
52+
__real_comm_demo_vsync();
53+
}
54+
}
55+
4756
static void assert_note_played_and_stopped(u8 pitch, u8 program)
4857
{
4958
assert_cc(CC_SHOW_PARAMETERS_ON_UI, 0x7F);
@@ -66,52 +75,106 @@ static void assert_note_played_and_stopped(u8 pitch, u8 program)
6675
void test_comm_demo_plays_note(UNUSED void** state)
6776
{
6877
will_return(__wrap_JOY_readJoypad, BUTTON_A);
78+
__real_comm_demo_read_ready();
6979

70-
for (int rep = 0; rep < 10; rep++) {
71-
assert_note_played_and_stopped(DEFAULT_PITCH, 0);
80+
while (__real_comm_demo_read_ready()) {
81+
__real_comm_demo_read();
7282
}
83+
84+
vsync_call(BUTTON_A);
85+
assert_note_off(DEFAULT_PITCH);
86+
assert_note_on(DEFAULT_PITCH, 127);
7387
}
7488

7589
void test_comm_demo_increases_pitch(UNUSED void** state)
7690
{
7791
will_return(__wrap_JOY_readJoypad, BUTTON_A);
78-
assert_note_played_and_stopped(DEFAULT_PITCH, 0);
92+
__real_comm_demo_read_ready();
93+
94+
while (__real_comm_demo_read_ready()) {
95+
__real_comm_demo_read();
96+
}
7997

8098
vsync_call(BUTTON_UP);
81-
assert_note_played_and_stopped(DEFAULT_PITCH + 1, 0);
99+
assert_note_off(DEFAULT_PITCH);
100+
assert_note_on(DEFAULT_PITCH + 1, 127);
82101
}
83102

84103
void test_comm_demo_decreases_pitch(UNUSED void** state)
85104
{
86105
will_return(__wrap_JOY_readJoypad, BUTTON_A);
87-
assert_note_played_and_stopped(DEFAULT_PITCH, 0);
106+
__real_comm_demo_read_ready();
107+
108+
while (__real_comm_demo_read_ready()) {
109+
__real_comm_demo_read();
110+
}
88111

89112
vsync_call(BUTTON_DOWN);
90-
assert_note_played_and_stopped(DEFAULT_PITCH - 1, 0);
113+
assert_note_off(DEFAULT_PITCH);
114+
assert_note_on(DEFAULT_PITCH - 1, 127);
91115
}
92116

93117
void test_comm_demo_increases_program(UNUSED void** state)
94118
{
95119
will_return(__wrap_JOY_readJoypad, BUTTON_A);
96-
assert_note_played_and_stopped(DEFAULT_PITCH, 0);
120+
__real_comm_demo_read_ready();
121+
122+
while (__real_comm_demo_read_ready()) {
123+
__real_comm_demo_read();
124+
}
97125

98126
vsync_call(BUTTON_RIGHT);
99-
assert_note_played_and_stopped(DEFAULT_PITCH, 1);
127+
assert_note_off(DEFAULT_PITCH);
128+
assert_program_change(1);
129+
assert_note_on(DEFAULT_PITCH, 127);
100130
}
101131

102132
void test_comm_demo_decreases_program(UNUSED void** state)
103133
{
104134
will_return(__wrap_JOY_readJoypad, BUTTON_A);
105-
assert_note_played_and_stopped(DEFAULT_PITCH, 0);
135+
__real_comm_demo_read_ready();
106136

107-
vsync_call(BUTTON_RIGHT);
108-
assert_note_played_and_stopped(DEFAULT_PITCH, 1);
137+
while (__real_comm_demo_read_ready()) {
138+
__real_comm_demo_read();
139+
}
109140

110141
vsync_call(BUTTON_RIGHT);
111-
assert_note_played_and_stopped(DEFAULT_PITCH, 2);
142+
assert_note_off(DEFAULT_PITCH);
143+
assert_program_change(1);
144+
assert_note_on(DEFAULT_PITCH, 127);
112145

113146
vsync_call(BUTTON_LEFT);
114-
assert_note_played_and_stopped(DEFAULT_PITCH, 1);
147+
assert_note_off(DEFAULT_PITCH);
148+
assert_program_change(0);
149+
assert_note_on(DEFAULT_PITCH, 127);
150+
}
151+
152+
void test_comm_demo_button_repeat_with_initial_delay(UNUSED void** state)
153+
{
154+
will_return(__wrap_JOY_readJoypad, BUTTON_A);
155+
__real_comm_demo_read_ready();
156+
157+
while (__real_comm_demo_read_ready()) {
158+
__real_comm_demo_read();
159+
}
160+
161+
vsync_call(BUTTON_UP);
162+
assert_note_off(DEFAULT_PITCH);
163+
assert_note_on(DEFAULT_PITCH + 1, 127);
164+
165+
vsync_call_multiple(BUTTON_UP, 38);
166+
assert_int_equal(__real_comm_demo_read_ready(), false);
167+
168+
vsync_call(BUTTON_UP);
169+
assert_note_off(DEFAULT_PITCH + 1);
170+
assert_note_on(DEFAULT_PITCH + 2, 127);
171+
172+
vsync_call_multiple(BUTTON_UP, 9);
173+
assert_int_equal(__real_comm_demo_read_ready(), false);
174+
175+
vsync_call(BUTTON_UP);
176+
assert_note_off(DEFAULT_PITCH + 2);
177+
assert_note_on(DEFAULT_PITCH + 3, 127);
115178
}
116179

117180
static void assert_read(u8 data)
@@ -131,7 +194,7 @@ static void assert_note_off(u8 pitch)
131194
{
132195
assert_read(0x80);
133196
assert_read(pitch);
134-
assert_read(127);
197+
assert_read(0);
135198
}
136199

137200
static void assert_cc(u8 cc, u8 value)

tests/unit/test_comm_demo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ void test_comm_demo_increases_pitch(UNUSED void** state);
88
void test_comm_demo_decreases_pitch(UNUSED void** state);
99
void test_comm_demo_increases_program(UNUSED void** state);
1010
void test_comm_demo_decreases_program(UNUSED void** state);
11+
void test_comm_demo_button_repeat_with_initial_delay(UNUSED void** state);

0 commit comments

Comments
 (0)