diff options
| -rw-r--r-- | sample_editor.html | 192 | ||||
| -rwxr-xr-x | sw/Core/Src/gfx.h | 4 | ||||
| -rwxr-xr-x | sw/Core/Src/plinky.c | 1 | ||||
| -rwxr-xr-x | sw/Core/Src/spi.h | 3 | ||||
| -rwxr-xr-x | sw/Core/Src/tinyusb/src/usbmidi.c | 4 | ||||
| -rwxr-xr-x | sw/Core/Src/webusb.h | 364 |
6 files changed, 432 insertions, 136 deletions
diff --git a/sample_editor.html b/sample_editor.html new file mode 100644 index 0000000..7322305 --- /dev/null +++ b/sample_editor.html @@ -0,0 +1,192 @@ +<!DOCTYPE html> +<html lang="en"> +<head> +<meta charset="UTF-8"> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> +<title>WebUSB App</title> +</head> +<body> +<button id="connect">Connect...</button> +<button id="send">Send</button> +<br/> +<canvas id="canvas" width="2048" height="256"></canvas> +<script> +let device; +let interfaceNumber; +let endpointIn; +let endpointOut; +let state = 0, cmd = 0, idx = 0, offset = 0, len = 0, big = 0, payload = []; + +function drawWaveform(bytes) { + const canvas = document.getElementById('canvas'); + const ctx = canvas.getContext('2d'); + const width = canvas.width = 2048; // ensure canvas is 2048 pixels wide + const height = canvas.height; + + // Clear canvas + ctx.clearRect(0, 0, width, height); + + // Interpret bytes as 16-bit little-endian signed integers + const values = []; + for (let i = 0; i < bytes.length; i += 2) { + const value = bytes[i] | (bytes[i + 1] << 8); // Little-endian conversion + values.push(value < 0x8000 ? value : value - 0x10000); // Interpret as signed + } + + // Scale and draw waveform + ctx.beginPath(); + for (let x = 0; x < values.length && x < width; x++) { + const y = ((-values[x] + 32768) / 65535) * height; // Map y range to canvas height + x === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y); + } + ctx.stroke(); +} + + +async function connectDevice() { + try { + device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0xcafe }] }); + await device.open(); + if (device.configuration === null) await device.selectConfiguration(1); + + const interfaces = device.configuration.interfaces; + for (const element of interfaces) { + for (const alternate of element.alternates) { + if (alternate.interfaceClass === 0xFF) { // Vendor-specific interface class + interfaceNumber = element.interfaceNumber; + for (const endpoint of alternate.endpoints) { + if (endpoint.direction === 'in') { + endpointIn = endpoint.endpointNumber; + } + if (endpoint.direction === 'out') { + endpointOut = endpoint.endpointNumber; + } + } + break; + } + } + } + + if (endpointIn === undefined || endpointOut === undefined) { + throw new Error('Endpoints not found'); + } + + await device.claimInterface(interfaceNumber); + await device.selectAlternateInterface(interfaceNumber, 0); + reset(0); // Reset state machine + console.log("Device connected:", device, endpointIn, endpointOut); + + // Change button to "Disconnect" + document.getElementById('connect').textContent = 'Disconnect'; + + // Send initial message and start reading loop + readLoop(); + } catch (error) { + console.error("Connection error:", error); + } +} + +async function disconnectDevice() { + try { + if (device) { + await device.close(); + device = null; + console.log("Device disconnected."); + } + reset(0); + document.getElementById('connect').textContent = 'Connect...'; + } catch (error) { + console.error("Disconnection error:", error); + } +} + +async function sendMsg(cmd, idx, offset, len, optionalData = []) { + const big = (offset>=65536 || len>=65536); + const header = big ? + [0xf3, 0x0f, 0xab, 0xcb, cmd, idx, offset & 255, (offset >> 8) & 255, (offset >> 16) & 255, offset >> 24, len & 255, (len >> 8) & 255, (len >> 16) & 255, len >> 24] : + [0xf3, 0x0f, 0xab, 0xca, cmd, idx, offset & 255, offset >> 8, len & 255, len >> 8]; + const message = header.concat(optionalData); + for (let i = 0; i < message.length; i += 64) { + const chunk = message.slice(i, i + 64); + console.log("Sending data:", chunk); + await device.transferOut(endpointOut, new Uint8Array(chunk)); + } +} + +async function readLoop() { + while (device) { + try { + const result = await device.transferIn(endpointIn, 64); + const data = new Uint8Array(result.data.buffer); + console.log("Received data:", data); + data.forEach(byte => processByte(byte)); + console.log("State:", state, big, cmd, idx, offset, len, payload.length); + } catch (error) { + console.error("Read error, device disconnected:", error); + disconnectDevice(); // Clean up on error + break; + } + } +} + +function reset(x) { + state = big = cmd = idx = offset = len = 0; + payload = []; + if (x === 0xf3) state = 1; + console.log("State reset. Starting state:", state); +} + +function processByte(x) { + switch (state) { + case 0: if (x === 0xf3) state++; else reset(x); break; + case 1: if (x === 0x0f) state++; else reset(x); break; + case 2: if (x === 0xab) state++; else reset(x); break; + case 3: big = (x=== 0xcb) ? 1 : 0; if (x === 0xca || x==0xcb) state++; else reset(x); break; + case 4: cmd = x; state++; break; + case 5: idx = x; state++; break; + case 6: offset = x; state++; break; + case 7: offset += x * 256; state=big ? 8 : 10; break; + case 8: offset += x * 65536; state++; break; + case 9: offset += x * 16777216; state++; break; + case 10: len = x; state++; break; + case 11: len += x * 256; + if (big) state++; else { + state=14; + if (len < 0) reset(x); + else if (len === 0) processPacket(); + } + break; + case 12: len += x * 65536; state++; break; + case 13: len += x * 16777216; state++; + if (len < 0) reset(x); + else if (len === 0) processPacket(); + break; + case 14: payload.push(x); len--; + if (len === 0) processPacket(); + break; + } +} + +function processPacket() { + console.log("Packet received:", { cmd, idx, offset, len, payload }); + drawWaveform(payload); + reset(); +} + +document.getElementById('connect').addEventListener('click', async () => { + if (device) { + await disconnectDevice(); + } else { + await connectDevice(); + } +}); + +document.getElementById('send').addEventListener('click', async () => { + if (device) { + idx=5; + await sendMsg(4, 0, 1031*2*idx, 1031*2); + } +}); +</script> +</body> +</html> diff --git a/sw/Core/Src/gfx.h b/sw/Core/Src/gfx.h index d5a33ff..28feed5 100755 --- a/sw/Core/Src/gfx.h +++ b/sw/Core/Src/gfx.h @@ -71,7 +71,7 @@ void vline(int x1, int y1, int y2, int c) { } else { *dst |= b1 & mask; dst += W; - for (; --n; dst += W) + if (--n) for (; --n; dst += W) *dst |= mask; *dst |= b2 & mask; } @@ -81,7 +81,7 @@ void vline(int x1, int y1, int y2, int c) { } else { *dst &= ~b1; dst += W; - for (; --n; dst += W) + if (--n) for (; --n; dst += W) *dst = 0; *dst &= ~b2; } diff --git a/sw/Core/Src/plinky.c b/sw/Core/Src/plinky.c index 14ffafe..5c45fc5 100755 --- a/sw/Core/Src/plinky.c +++ b/sw/Core/Src/plinky.c @@ -681,6 +681,7 @@ int arpdebugi; #endif +extern const short wavetable[17][1031]; //s16 wavetable[WAVETABLE_SIZE*WT_LAST]; #ifndef EMU diff --git a/sw/Core/Src/spi.h b/sw/Core/Src/spi.h index 9affd1f..b69e7e8 100755 --- a/sw/Core/Src/spi.h +++ b/sw/Core/Src/spi.h @@ -46,7 +46,8 @@ void spi_read_done(void) { resetspistate(); } else { int dacchan = spistate-MAX_SPI_STATE; - spi_update_dac(dacchan); + if (dacchan<4 && dacchan>=0) + spi_update_dac(dacchan); } } else { diff --git a/sw/Core/Src/tinyusb/src/usbmidi.c b/sw/Core/Src/tinyusb/src/usbmidi.c index 39bf514..70b153d 100755 --- a/sw/Core/Src/tinyusb/src/usbmidi.c +++ b/sw/Core/Src/tinyusb/src/usbmidi.c @@ -180,12 +180,14 @@ int miditest(void) { void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; + web_serial_connected = true; } // Invoked when device is unmounted void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; + web_serial_connected = false; } // Invoked when usb bus is suspended @@ -195,12 +197,14 @@ void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; + web_serial_connected = false; } // Invoked when usb bus is resumed void tud_resume_cb(void) { blink_interval_ms = BLINK_MOUNTED; + web_serial_connected = true; } //--------------------------------------------------------------------+ diff --git a/sw/Core/Src/webusb.h b/sw/Core/Src/webusb.h index 495acd7..76da03e 100755 --- a/sw/Core/Src/webusb.h +++ b/sw/Core/Src/webusb.h @@ -1,6 +1,6 @@ #pragma once #ifdef DEBUG -#define DEBUG_WU +//#define DEBUG_WU #endif #ifdef DEBUG_WU #define WUDebugLog DebugLog @@ -11,153 +11,251 @@ #ifdef EMU static inline uint32_t tud_vendor_write_available(void) { return 0; } static inline uint32_t tud_vendor_available(void) { return 0; } -static inline uint32_t tud_vendor_read(void* buffer, uint32_t bufsize) { return 0; } -static inline uint32_t tud_vendor_write(const void* buffer, uint32_t bufsize) { return 0; } +static inline uint32_t tud_vendor_read(void *buffer, uint32_t bufsize) { return 0; } +static inline uint32_t tud_vendor_write(const void *buffer, uint32_t bufsize) { return 0; } #else -uint32_t tud_vendor_n_write_available (uint8_t itf); -uint32_t tud_vendor_n_available (uint8_t itf); -uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); -uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); -static inline uint32_t tud_vendor_write_available (void) -{ - return tud_vendor_n_write_available(0); -} -static inline uint32_t tud_vendor_available (void) -{ - return tud_vendor_n_available(0); -} -static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) -{ - return tud_vendor_n_read(0, buffer, bufsize); -} -static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize) -{ - return tud_vendor_n_write(0, buffer, bufsize); -} +uint32_t tud_vendor_n_write_available(uint8_t itf); +uint32_t tud_vendor_n_available(uint8_t itf); +uint32_t tud_vendor_n_read(uint8_t itf, void *buffer, uint32_t bufsize); +uint32_t tud_vendor_n_write(uint8_t itf, void const *buffer, uint32_t bufsize); +static inline uint32_t tud_vendor_write_available(void) { return tud_vendor_n_write_available(0); } +static inline uint32_t tud_vendor_available(void) { return tud_vendor_n_available(0); } +static inline uint32_t tud_vendor_read(void *buffer, uint32_t bufsize) { return tud_vendor_n_read(0, buffer, bufsize); } +static inline uint32_t tud_vendor_write(void const *buffer, uint32_t bufsize) { return tud_vendor_n_write(0, buffer, bufsize); } #endif -/* webusb wire format. 10 byte header, then data. + +extern const short wavetable[17][1031]; + +/* webusb wire format. 10 byte header, then data. u32 magic = 0xf30fabca u8 cmd // 0 = get, 1=set u8 idx // 0 -u8 idx2 // 0 +u8 idx2 // 0 u8 idx3 // 0 u16 datalen // in bytes, not including this header, 0 for get, 1552 for set */ typedef struct WebUSBHeader { // 10 byte header - u8 magic[4]; - u8 cmd,idx; - u16 offset; - u16 len; -} WebUSBHeader; -const static u8 wu_magic[4] = { 0xf3,0x0f,0xab,0xca }; // we expect magic to be these -const static u8 wu_magic_ext[4] = { 0xf4,0x1f,0xcb,0xdb }; // we expect magic to be these + u8 magic[4]; + u8 cmd, idx; + union { + struct { + u16 offset_16; + u16 len_16; + }; + struct { // these are valid if magic3 is 0xcc + u32 offset_32; + u32 len_32; + }; + }; +} __attribute__((packed)) WebUSBHeader; +const static u8 wu_magic[4] = {0xf3, 0x0f, 0xab, 0xca}; +const static u8 wu_magic_ext[4] = {0xf3, 0x0f, 0xab, 0xcb}; // 32 bit version #define WEB_USB_TIMEOUT 500 enum { // state machine ticks thru these in order, more or less - WU_MAGIC0, - WU_MAGIC1, - WU_MAGIC2, - WU_MAGIC3, - WU_RECVHDR, - WU_RECVDATA, - WU_SENDHDR, - WU_SENDDATA, + WU_MAGIC0, + WU_MAGIC1, + WU_MAGIC2, + WU_MAGIC3, + WU_RECVHDR, + WU_RECVDATA, + WU_SENDHDR, + WU_SENDDATA, }; u8 wu_state = WU_MAGIC0; // current state -WebUSBHeader wu_hdr; // header of current command -u8* wu_data=(u8*)&wu_hdr; // buffer where we are reading/writing atm -int wu_len=1; // how much left to read/write before state transition -int wu_lasteventtime; // for timeout detection -void SetWUState(u8 state, u8* data, int len) { wu_state = state; wu_data = data; wu_len = len; } +WebUSBHeader wu_hdr; // header of current command +int is_wu_hdr_32bit(void) { return wu_hdr.magic[3] == wu_magic_ext[3]; } +int wu_hdr_len(void) { return is_wu_hdr_32bit() ? wu_hdr.len_32 : wu_hdr.len_16; } +int wu_hdr_offset(void) { return is_wu_hdr_32bit() ? wu_hdr.offset_32 : wu_hdr.offset_16; } +u8 *wu_data = (u8 *)&wu_hdr; // buffer where we are reading/writing atm +int wu_len = 1; // how much left to read/write before state transition +int wu_lasteventtime; // for timeout detection +void SetWUState(u8 state, u8 *data, int len) { + wu_state = state; + wu_data = data; + wu_len = len; +} void PumpWebUSB() { - while (1) { - if (millis() > wu_lasteventtime + WEB_USB_TIMEOUT) { // timeout! - reset: - SetWUState(WU_MAGIC0, wu_hdr.magic, 1); - } - int n; - if (wu_state < WU_SENDHDR) { // receive - //n = tud_vendor_available(); - //if (n<6) break; - n = tud_vendor_read(wu_data, wu_len); - } - else { // send - if (wu_len <= 0) { - // odd corner case. the state doesnt want to send anything. just pretend the state is done - goto statedone; - } - n = tud_vendor_write_available(); - if (n > wu_len) n = wu_len; - if (n <= 0) break; - n = tud_vendor_write(wu_data, n); - } - if (n <= 0) break; // nothing to do + bool need_tud_task = false; + while (1) { + need_tud_task = true; + if (millis() > wu_lasteventtime + WEB_USB_TIMEOUT) { // timeout! + reset: + SetWUState(WU_MAGIC0, wu_hdr.magic, 1); + } + int n; + if (wu_state < WU_SENDHDR) { // receive + // n = tud_vendor_available(); + // if (n<6) break; + if (need_tud_task) + tud_task(); + + n = tud_vendor_read(wu_data, wu_len); + } else { // send + if (wu_len <= 0) { + // odd corner case. the state doesnt want to send anything. just pretend the state is done + goto statedone; + } + n = tud_vendor_write_available(); + if (n > wu_len) + n = wu_len; + if (n <= 0) + break; + n = tud_vendor_write(wu_data, n); + } + if (n <= 0) + break; // nothing to do #ifdef DEBUG_WU - WUDebugLog("%d (%d): ", wu_state,wu_len); - for (int i=0;i<n;++i) WUDebugLog("%02x ", wu_data[i]); - WUDebugLog("\r\n"); + WUDebugLog("%d (%d): ", wu_state, wu_len); + for (int i = 0; i < n; ++i) + WUDebugLog("%02x ", wu_data[i]); + WUDebugLog("\r\n"); #endif - wu_lasteventtime = millis(); - wu_len -= n; - wu_data += n; - if (wu_len > 0) break; // not done with this state yet. next time! - // ok! end of a state. whats next -statedone: - switch (wu_state) { - case WU_MAGIC0: case WU_MAGIC1: case WU_MAGIC2: case WU_MAGIC3: { - u8 m = wu_hdr.magic[wu_state]; - if (m != wu_magic[wu_state]) { - WUDebugLog("magic fail %02x %02x\r\n",m, wu_magic[wu_state]); - wu_hdr.magic[0] = m; - wu_len = 1; - wu_state = (m == wu_magic[0]) ? WU_MAGIC1 : WU_MAGIC0; // if we got the first byte, we can tick into next state! - wu_data = wu_hdr.magic + wu_state; - continue; - } - wu_state++; - wu_len = 1; - if (wu_state == WU_RECVHDR) { // time to get rest of header - WUDebugLog("get header!\r\n"); - wu_len = 10-4; - } - continue; } - case WU_RECVHDR: // ok we got the header. what do they want: - WUDebugLog("got header %d %d!\r\n", wu_hdr.cmd,wu_hdr.len); - if (wu_hdr.cmd > 1) goto reset; // invalid cmd? - if (wu_hdr.cmd == 0) { - // they asked to get a preset! - if (wu_hdr.len + wu_hdr.offset > sizeof(Preset) ) goto reset; - if (wu_hdr.offset >= sizeof(Preset)) goto reset; - if (wu_hdr.idx >= 32) wu_hdr.idx = sysparams.curpreset; - wu_hdr.cmd = 1; - if (wu_hdr.len == 0) - wu_hdr.len = sizeof(Preset) - wu_hdr.offset; - SetWUState(WU_SENDHDR, (u8*)&wu_hdr, 10); - } - else { - // they asked to set! - if (wu_hdr.len + wu_hdr.offset > sizeof(Preset) || wu_hdr.len<=0) goto reset; - if (wu_hdr.offset >= sizeof(Preset)) goto reset; - if (wu_hdr.idx >= 32) wu_hdr.idx = sysparams.curpreset; // idx>32, just use current - // switch to the specified preset ready to receive. - SetPreset(wu_hdr.idx, false); - SetWUState(WU_RECVDATA, ((u8*)&rampreset) + wu_hdr.offset, wu_hdr.len); - } - continue; - case WU_RECVDATA: - if (wu_hdr.cmd == 1) { - // finished receiving preset. mark it dirty - ramtime[GEN_PRESET] = millis(); - } - goto reset; - case WU_SENDHDR:// ok we sent them the header; now send them the data - { - u8* data = (wu_hdr.idx == sysparams.curpreset) ? (u8 * )&rampreset : (u8*)GetSavedPreset(wu_hdr.idx); - SetWUState(WU_SENDDATA, data + wu_hdr.offset, wu_hdr.len); - continue; - } - case WU_SENDDATA: // ok we finished sending our data. nothing to do except get ready for more. - goto reset; - } // state - } // while loop + wu_lasteventtime = millis(); + wu_len -= n; + wu_data += n; + if (wu_len > 0) { + continue; // used to be break! + } + // ok! end of a state. whats next + statedone: + switch (wu_state) { + case WU_MAGIC0: + case WU_MAGIC1: + case WU_MAGIC2: + case WU_MAGIC3: { + u8 m = wu_hdr.magic[wu_state]; + if (m != wu_magic[wu_state] && m != wu_magic_ext[wu_state]) { + WUDebugLog("magic fail %02x %02x\r\n", m, wu_magic[wu_state]); + // this resyncs to the incoming message! + wu_hdr.magic[0] = m; + wu_len = 1; + wu_state = (m == wu_magic[0]) ? WU_MAGIC1 : WU_MAGIC0; // if we got the first byte, we can tick into next state! + wu_data = wu_hdr.magic + wu_state; + continue; + } + wu_state++; + wu_len = 1; + if (wu_state == WU_RECVHDR) { // time to get rest of header + WUDebugLog("get header!\r\n"); + wu_len = 10 - 4; + if (is_wu_hdr_32bit()) + wu_len = 14 - 4; + } + continue; + } + case WU_RECVHDR: { // ok we got the header. what do they want: + WUDebugLog("got header %d %d!\r\n", wu_hdr.cmd, wu_hdr_len()); + if (wu_hdr.cmd >= 6) + goto reset; // invalid cmd? + int maxsize = (wu_hdr.idx >= 64) ? sizeof(SampleInfo) : sizeof(Preset); + if (wu_hdr.cmd<2) { + if (wu_hdr.idx >= 64 + 8) + wu_hdr.idx = ((ramsample1_idx - 1) & 7) + 64; + else if (wu_hdr.idx >= 32) + wu_hdr.idx = sysparams.curpreset; + } else if (wu_hdr.cmd ==2 || wu_hdr.cmd == 3) { + maxsize= 1024*1024*32; + } else if (wu_hdr.cmd ==4 || wu_hdr.cmd == 5) { + maxsize=sizeof(wavetable); + } + if (wu_hdr_len() + wu_hdr_offset() > maxsize || wu_hdr_len() < 0 || wu_hdr_offset() < 0) + goto reset; + if (wu_hdr.cmd == 4) { + // read wavetable ram + wu_hdr.cmd = 5; + int ofs = wu_hdr_offset(); + int len = wu_hdr_len(); + wu_hdr.len_32 = len; + wu_hdr.offset_32 = ofs; + wu_hdr.magic[3] = wu_magic_ext[3]; // 32 bit mode + SetWUState(WU_SENDHDR, (u8 *)&wu_hdr, is_wu_hdr_32bit() ? 14 : 10); + } else if (wu_hdr.cmd == 2) { + // read sample ram + wu_hdr.cmd = 3; + wu_hdr.idx &= 7; + int ofs = wu_hdr_offset(); + int len = wu_hdr_len(); + wu_hdr.len_32 = len; + wu_hdr.offset_32 = ofs; + wu_hdr.magic[3] = wu_magic_ext[3]; // 32 bit mode + SetWUState(WU_SENDHDR, (u8 *)&wu_hdr, is_wu_hdr_32bit() ? 14 : 10); + } else if (wu_hdr.cmd == 0) { + wu_hdr.cmd = 1; + if (wu_hdr_len() == 0) { + int ofs = wu_hdr_offset(); + wu_hdr.len_16 = maxsize - ofs; + wu_hdr.offset_16 = ofs; + wu_hdr.magic[3] = wu_magic[3]; // 16 bit mode + } + SetWUState(WU_SENDHDR, (u8 *)&wu_hdr, is_wu_hdr_32bit() ? 14 : 10); + } else if (wu_hdr.cmd == 1) { + // they asked to set! + if (wu_hdr.idx >= 64 && wu_hdr.idx < 64 + 8) { + cur_sample1 = wu_hdr.idx - 64 + 1; + CopySampleToRam(false); + ramsample1_idx = cur_sample1; + SetWUState(WU_RECVDATA, ((u8 *)&ramsample) + wu_hdr_offset(), wu_hdr_len()); + } else { + SetPreset(wu_hdr.idx, false); + SetWUState(WU_RECVDATA, ((u8 *)&rampreset) + wu_hdr_offset(), wu_hdr_len()); + } + } else + goto reset; + continue; + } + case WU_RECVDATA: + if (wu_hdr.cmd == 1) { + // finished receiving preset. mark it dirty + if (wu_hdr.idx >= 64) { + ramtime[GEN_SAMPLE] = millis(); + } else + ramtime[GEN_PRESET] = millis(); + } else if (wu_hdr.cmd == 3) { + // TODO: write to spi ram + } else if (wu_hdr.cmd == 5) { + // TODO: write to wavetable ram + } + goto reset; + case WU_SENDHDR: // ok we sent them the header; now send them the data + send_more_data: { + int len = wu_hdr_len(); + int ofs = wu_hdr_offset(); + + u8 *data; + if (wu_hdr.cmd == 5) { // send wavetable data + SetWUState(WU_SENDDATA, ((u8 *)&wavetable) + ofs, len); + } else if (wu_hdr.cmd == 3) { // send spi data + if (len > 256) + len = 256; + wu_hdr.len_32 -= len; + wu_hdr.offset_32 += len; + while (spistate) + ; + spistate = 255; + memset(spibigrx, -2, sizeof(spibigrx)); + spi_read256(ofs); + SetWUState(WU_SENDDATA, spibigrx + 4, len); + } else if (wu_hdr.cmd == 1) { + if (wu_hdr.idx == ((ramsample1_idx - 1) & 7) + 64) + data = (u8 *)&ramsample; + else if (wu_hdr.idx >= 64 && wu_hdr.idx < 64 + 8) + data = (u8 *)GetSavedSampleInfo(wu_hdr.idx - 64); + else + data = (wu_hdr.idx == sysparams.curpreset) ? (u8 *)&rampreset : (u8 *)GetSavedPreset(wu_hdr.idx); + SetWUState(WU_SENDDATA, data + wu_hdr_offset(), wu_hdr_len()); + } + continue; + } + case WU_SENDDATA: // ok we finished sending our data. nothing to do except get ready for more. + if (wu_hdr.cmd == 3) { + if (wu_hdr.len_32 <= 0) { + spistate = 0; + } else { + goto send_more_data; + } + } + goto reset; + } // state + } // while loop } |
