Skip to content

Commit 932801e

Browse files
author
Yatao Li
committed
syx sound send is working
1 parent 5fb8811 commit 932801e

File tree

8 files changed

+159
-87
lines changed

8 files changed

+159
-87
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ avr/cores/megacommand/**/*.d
1515
avr/cores/megacommand/**/*.hex
1616
avr/cores/megacommand/**/*.elf
1717
avr/cores/megacommand/**/*.a
18-
18+
sym_*.txt

avr/cores/megacommand/MCL/SoundBrowserPage.cpp

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44
const char *c_sound_root = "/Sounds/MD";
55
const char *c_snd_suffix = ".snd";
66
const char *c_wav_suffix = ".wav";
7+
const char *c_syx_suffix = ".syx";
78

89
const char *c_snd_name = "SOUND";
910
const char *c_wav_name = "WAV";
11+
const char *c_syx_name = "SYSEX";
1012

1113
static bool s_query_returned = false;
1214

1315
#define FT_SND 0
1416
#define FT_WAV 1
17+
#define FT_SYX 2
1518

1619
#define PA_NEW 0
1720
#define PA_SELECT 1
@@ -37,9 +40,11 @@ void SoundBrowserPage::init() {
3740

3841
filetypes[0] = c_snd_suffix;
3942
filetypes[1] = c_wav_suffix;
43+
filetypes[2] = c_syx_suffix;
4044
filetype_names[0] = c_snd_name;
4145
filetype_names[1] = c_wav_name;
42-
filetype_max = FT_WAV;
46+
filetype_names[2] = c_syx_name;
47+
filetype_max = FT_SYX;
4348

4449
if (show_samplemgr) {
4550
strcpy(title, "MD-ROM");
@@ -55,8 +60,7 @@ void SoundBrowserPage::init() {
5560
strcpy(match, ".snd");
5661
strcpy(title, "Sounds");
5762
show_dirs = true;
58-
show_save = true;
59-
//show_save = (filetype_idx == FT_SND);
63+
show_save = (filetype_idx != FT_SYX);
6064
show_filemenu = true;
6165
show_new_folder = true;
6266
show_overwrite = true;
@@ -118,14 +122,23 @@ void SoundBrowserPage::load_sound() {
118122
}
119123
}
120124

121-
// send current selected wav file to slot
122-
void SoundBrowserPage::send_wav(int slot) {
125+
// send current selected sample file to slot
126+
void SoundBrowserPage::send_sample(int slot, bool is_syx) {
127+
bool success;
123128
if (file.isOpen()) {
124129
char temp_entry[FILE_ENTRY_SIZE];
125130
file.getName(temp_entry, FILE_ENTRY_SIZE);
126131
file.close();
127-
midi_sds.sendWav(temp_entry, slot, /* show progress */ true);
128-
gfx.alert("Sample sent", temp_entry);
132+
if (is_syx) {
133+
success = midi_sds.sendSyx(temp_entry, slot);
134+
} else {
135+
success = midi_sds.sendWav(temp_entry, slot, /* show progress */ true);
136+
}
137+
if (success) {
138+
gfx.alert("Sample sent", temp_entry);
139+
} else {
140+
gfx.alert("Send failed", temp_entry);
141+
}
129142
}
130143
}
131144

@@ -181,6 +194,7 @@ void SoundBrowserPage::on_select(const char *__) {
181194
load_sound();
182195
break;
183196
case FT_WAV:
197+
case FT_SYX:
184198
pending_action = PA_SELECT;
185199
show_samplemgr = true;
186200
show_ram_slots = false;
@@ -190,12 +204,12 @@ void SoundBrowserPage::on_select(const char *__) {
190204
} else {
191205
auto slot = encoders[1]->cur;
192206
switch (pending_action) {
193-
case PA_NEW:
194-
recv_wav(slot);
195-
break;
196-
case PA_SELECT:
197-
send_wav(slot);
198-
break;
207+
case PA_NEW:
208+
recv_wav(slot);
209+
break;
210+
case PA_SELECT:
211+
send_sample(slot, (filetype_idx == FT_SYX));
212+
break;
199213
}
200214
show_samplemgr = false;
201215
init();

avr/cores/megacommand/MCL/SoundBrowserPage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class SoundBrowserPage : public FileBrowserPage, public MidiSysexListenerClass {
2929
void cleanup();
3030
void save_sound();
3131
void load_sound();
32-
void send_wav(int slot);
32+
void send_sample(int slot, bool is_syx);
3333
void recv_wav(int slot);
3434

3535
// MidiSysexListenerClass

avr/cores/megacommand/Midi/MidiSDS.cpp

Lines changed: 108 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "MCL_impl.h"
2+
#include "MidiSysexFile.h"
23

34
void MidiSDSClass::sendGeneralMessage(uint8_t type) {
45
uint8_t data[6] = {0xF0, 0x7E, 0x00, 0x00, 0x00, 0xF7};
@@ -41,6 +42,21 @@ void MidiSDSClass::sendDumpRequest(uint16_t slot) {
4142
MidiUart.sendRaw(data, 7);
4243
}
4344

45+
uint8_t MidiSDSClass::waitForHandshake() {
46+
uint8_t rep;
47+
wait:
48+
rep = waitForMsg();
49+
if (rep == MIDI_SDS_ACK) {
50+
hand_shake_state = true;
51+
} else if (rep == MIDI_SDS_WAIT) {
52+
goto wait;
53+
} else {
54+
// HandShake disabled.
55+
hand_shake_state = false;
56+
}
57+
return rep;
58+
}
59+
4460
uint8_t MidiSDSClass::waitForMsg(uint16_t timeout) {
4561

4662
MidiSDSSysexListener.msgType = 255;
@@ -56,6 +72,7 @@ uint8_t MidiSDSClass::waitForMsg(uint16_t timeout) {
5672
(MidiSDSSysexListener.msgType == 255));
5773
return MidiSDSSysexListener.msgType;
5874
}
75+
5976
void MidiSDSClass::cancel() {
6077
DEBUG_PRINTLN(F("cancelling transmission"));
6178
wav_file.close();
@@ -93,6 +110,95 @@ static void _setName(const char *filename, uint16_t slot) {
93110
MD.setSampleName(slot, name);
94111
}
95112

113+
bool MidiSDSClass::sendSyx(const char *filename, uint16_t sample_number) {
114+
MidiSysexFile file;
115+
uint8_t buf[256];
116+
int szbuf;
117+
bool ret = true;
118+
uint8_t reply;
119+
uint32_t fsize;
120+
int show_progress = 0;
121+
uint8_t n_retry = 0;
122+
123+
if (state != SDS_READY || !file.open(filename, O_READ)) {
124+
return false;
125+
}
126+
127+
file.seekEnd();
128+
fsize = file.position();
129+
file.seek(0);
130+
131+
// 1st packet: sysex request.
132+
szbuf = file.readPacket(buf, sizeof(buf));
133+
if (szbuf == -1 || buf[1] != 0x7E || buf[3] != 0x01) {
134+
ret = false;
135+
goto cleanup;
136+
}
137+
buf[4] = sample_number & 0x7F;
138+
buf[5] = (sample_number >> 7) & 0x7F;
139+
MidiUart.sendRaw(buf, szbuf);
140+
state = SDS_SEND;
141+
reply = waitForHandshake();
142+
if (reply == MIDI_SDS_CANCEL) {
143+
ret = false;
144+
goto cleanup;
145+
}
146+
147+
oled_display.clearDisplay();
148+
149+
while(true) {
150+
const uint32_t pos = file.position();
151+
DEBUG_PRINT("pos = ");
152+
DEBUG_PRINTLN(pos);
153+
DEBUG_PRINT("fsize = ");
154+
DEBUG_PRINTLN(fsize);
155+
if (pos >= fsize) {
156+
break;
157+
}
158+
if (++show_progress > 10) {
159+
show_progress = 0;
160+
mcl_gui.draw_progress("Sending sample", pos * 80 / fsize ,80);
161+
}
162+
szbuf = file.readPacket(buf, sizeof(buf));
163+
if (szbuf == -1) {
164+
ret = false;
165+
goto cleanup;
166+
}
167+
n_retry = 0;
168+
retry:
169+
MidiUart.sendRaw(buf, szbuf);
170+
if (!hand_shake_state) {
171+
delay(200);
172+
} else if (buf[1] == 0x7E && buf[3] == 0x02) {
173+
reply = waitForMsg(20);
174+
switch (reply) {
175+
case 255: // nothing came back
176+
hand_shake_state = false;
177+
goto retry;
178+
case MIDI_SDS_WAIT:
179+
reply = waitForMsg();
180+
if (reply != MIDI_SDS_ACK) {
181+
ret = false;
182+
goto cleanup;
183+
}
184+
case MIDI_SDS_ACK:
185+
break;
186+
default:
187+
if(n_retry++ > 3) {
188+
ret = false;
189+
goto cleanup;
190+
}
191+
goto retry;
192+
}
193+
} // otherwise, don't expect ACK reply (maybe MD-specific name-setting command)
194+
}
195+
// later packets
196+
197+
cleanup:
198+
file.close();
199+
state = SDS_READY;
200+
return ret;
201+
}
96202

97203
bool MidiSDSClass::sendWav(const char *filename, uint16_t sample_number, bool show_progress) {
98204
if (state != SDS_READY) {
@@ -125,19 +231,11 @@ bool MidiSDSClass::sendWav(const char *filename, uint16_t sample_number, bool sh
125231
uint8_t rep = 0;
126232

127233
midi_sds.state = SDS_SEND;
128-
wait:
129-
rep = waitForMsg();
130-
if (rep == MIDI_SDS_ACK) {
131-
hand_shake_state = true;
132-
} else if (rep == MIDI_SDS_CANCEL) {
234+
rep = waitForHandshake();
235+
if (rep == MIDI_SDS_CANCEL) {
133236
cancel();
134237
wav_file.close();
135238
return false;
136-
} else if (rep == MIDI_SDS_WAIT) {
137-
goto wait;
138-
} else {
139-
// HandShake disabled.
140-
hand_shake_state = false;
141239
}
142240

143241
_setName(filename, sample_number);

avr/cores/megacommand/Midi/MidiSDS.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class MidiSDSClass {
5050

5151
void setSampleRate(uint32_t hz) { samplePeriod = (uint32_t)1000000000 / hz; }
5252
uint8_t waitForMsg(uint16_t timeout = 2000);
53+
uint8_t waitForHandshake();
54+
bool sendSyx(const char *filename, uint16_t sample_number);
5355
bool sendWav(const char *filename, uint16_t sample_number, bool show_progress = false);
5456
bool sendSamples(bool show_progress);
5557
bool recvWav(const char *filename, uint16_t sample_number /* always show progress */);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include "MidiSysexFile.h"
2+
3+
int MidiSysexFile::readPacket(uint8_t* buf, size_t szbuf) {
4+
uint8_t *p = buf;
5+
do {
6+
*p = FatFile::read();
7+
} while (*p++ != 0xF7 && --szbuf > 0);
8+
if(buf[0] == 0xF0 && p[-1] == 0xF7) {
9+
return p - buf;
10+
} else {
11+
return -1;
12+
}
13+
}
Lines changed: 6 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,11 @@
1-
#ifndef MIDISYSEXFILE_H__
2-
#define MIDISYSEXFILE_H__
3-
4-
#include "MidiUart.h"
5-
6-
class MidiSysexFile {
1+
#pragma once
2+
#include "MCLSd.h"
73

4+
class MidiSysexFile: public File {
85
public:
9-
MidiUartClass *uart;
10-
File file;
11-
12-
MidiSysexFile(MidiClass *_midi) { uart = (MidiUartClass*)_midi->uart; }
13-
14-
bool send(char *file_name) {
15-
16-
bool ret;
17-
ret = file.open(file_name, O_READ);
18-
19-
if (!ret) {
20-
DEBUG_PRINTLN("Could not open SYSEX file:");
21-
DEBUG_PRINTLN(file_name);
22-
return false;
23-
}
24-
25-
uint8_t buf[512];
26-
27-
uint32_t file_size = file.fileSize();
28-
29-
uint32_t bytes_read = 0;
30-
31-
while (bytes_read < file_size) {
32-
33-
uint16_t len;
34-
35-
if (file_size - bytes_read < 512) {
36-
len = file_size - bytes_read;
37-
} else {
38-
len = 512;
39-
}
40-
41-
if (mcl_sd.read_data(&buf, len, &file)) {
42-
bytes_read += len;
43-
} else {
44-
DEBUG_PRINTLN("failed to send");
45-
return false;
46-
}
47-
48-
if (bytes_read == 0 && buf[0] != 0xF0) {
49-
DEBUG_PRINTLN("incorrect file type");
50-
return false;
51-
}
52-
for (uint8_t c = 0; c < len; c++) {
53-
while (uart->txRb.isFull())
54-
;
55-
uart->m_putc(buf[c]);
56-
}
57-
}
586

59-
return true;
60-
}
61-
bool recv();
7+
MidiSysexFile() : File() {}
8+
// returns -1 if a sysex packet cannot be read.
9+
int readPacket(uint8_t* buf, size_t szbuf);
6210
};
6311

64-
#endif /* MIDISYSEXFILE_H__ */

syms.ps1

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ function parse-symbol($line) {
2727
} catch {}
2828
}
2929

30-
Set-Location sketch
31-
$lines = $(avr-objdump -x build/MIDICtrl20_MegaCommand.avr.mega\sketch.ino.elf)
30+
$lines = $(avr-objdump -x bin\sketch.ino.elf)
3231
$header = $lines | Select-Object -First 37
3332
$symbols = $lines | Select-Object -Skip 38 | %{ parse-symbol($_) }
3433

@@ -52,4 +51,3 @@ echo "Total compressable object size: $comp_total_size"
5251

5352
$data | Out-GridView
5453
$bss | Out-GridView
55-
Set-Location ..

0 commit comments

Comments
 (0)