сделал запись трека через юсб

This commit is contained in:
VladislavOstapov 2023-11-02 16:33:31 +03:00
parent b3b04f5714
commit 4622e29d02
4 changed files with 136 additions and 217 deletions

View File

@ -0,0 +1,27 @@
#ifndef FLOPPOTRON_FLOPPY_INTERFACE_H
#define FLOPPOTRON_FLOPPY_INTERFACE_H
#include "main.h"
#define FLOPPY_MAX_TRACK_SIZE 4096
#ifdef __cplusplus
extern "C" {
#endif
// статус Floppy-проигрывателя
enum FloppyStatus_t {
FP_READY = 0,
FP_PLAY,
FP_PAUSE,
};
extern enum FloppyStatus_t FloppyStatus;
extern uint16_t FloppyTrack[FLOPPY_MAX_TRACK_SIZE];
void FloppyPutData(const uint8_t* data, size_t len);
#ifdef __cplusplus
};
#endif
#endif //FLOPPOTRON_FLOPPY_INTERFACE_H

View File

@ -0,0 +1,61 @@
#include <cstring>
#include "floppy-interface.h"
FloppyStatus_t FloppyStatus = FP_READY;
uint16_t FloppyTrack[FLOPPY_MAX_TRACK_SIZE];
void fpPutChar(uint8_t ch) {
// состояния: 0 - ожидание байта длинны 1, 1 - ожидание байта длинны 2, 2 - ожидание команды, 3 - прием данных в случае команды записи трека
static int state = 0;
static uint16_t cmd_len;
static size_t trackWriteIndex;
switch (state) {
case 0: // старший байт
cmd_len = ch;
state = 1;
break;
case 1: // младший байт
cmd_len <<= 8;
cmd_len |= ch;
state = 2;
break;
case 2:
if (ch == 10) {
// запись трека, игнорируем размер посылки
FloppyStatus = FP_READY;
memset(FloppyTrack, 0, sizeof(FloppyTrack));
trackWriteIndex = 0;
state = 3;
} else if (ch == 1) {
// установка FP_PLAY
FloppyStatus = FP_PLAY;
state = 0;
} else if (ch == 2) {
// установка FP_PAUSE
FloppyStatus = FP_PAUSE;
state = 0;
}
break;
case 3:
// длинна "заголовка" = 3 байта - 2 байта длинны
*(((uint8_t*)FloppyTrack) + (trackWriteIndex++)) = ch;
if (trackWriteIndex + 1 >= cmd_len) {
state = 0;
}
break;
default:
state = 0;
}
}
void FloppyPutData(const uint8_t* data, size_t len) {
while (len--) {
fpPutChar(*data++);
}
}

View File

@ -1,4 +1,5 @@
#include "floppy.h"
#include "floppy-interface.h"
#include "main.h"
#define FLOPPOTRON_TICK_SPEED (uint16_t)(72000000 / 3600)
@ -121,231 +122,60 @@ void FloppyDriveInitialize() {
// хандлер для проигрывания нот
void FloppyTrackTick() {
// байткод для 100bpm, тестовая мелодия
const static uint16_t bytecode[] = {
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 165, FT_CMD_WAIT | 50, // '3'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 196, FT_CMD_WAIT | 50, // '5'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 165, FT_CMD_WAIT | 50, // '3'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 196, FT_CMD_WAIT | 50, // '5'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 147, FT_CMD_WAIT | 50, // '2'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 196, FT_CMD_WAIT | 50, // '5'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 147, FT_CMD_WAIT | 50, // '2'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 196, FT_CMD_WAIT | 50, // '5'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 147, FT_CMD_WAIT | 50, // '2'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 174, FT_CMD_WAIT | 50, // '4'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 147, FT_CMD_WAIT | 50, // '2'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 174, FT_CMD_WAIT | 50, // '4'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 147, FT_CMD_WAIT | 50, // '2'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 220, FT_CMD_WAIT | 50, // '6'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 174, FT_CMD_WAIT | 50, // '4'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 220, FT_CMD_WAIT | 50, // '6'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 147, FT_CMD_WAIT | 50, // '2'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 220, FT_CMD_WAIT | 50, // '6'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 174, FT_CMD_WAIT | 50, // '4'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 220, FT_CMD_WAIT | 50, // '6'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 165, FT_CMD_WAIT | 50, // '3'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 196, FT_CMD_WAIT | 50, // '5'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 174, FT_CMD_WAIT | 50, // '4'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 196, FT_CMD_WAIT | 50, // '5'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 262, FT_CMD_WAIT | 50, // '1''
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 147, FT_CMD_WAIT | 50, // '2'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 174, FT_CMD_WAIT | 50, // '4'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 196, FT_CMD_WAIT | 50, // '5'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 174, FT_CMD_WAIT | 50, // '4'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 196, FT_CMD_WAIT | 50, // '5'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 220, FT_CMD_WAIT | 50, // '6'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 196, FT_CMD_WAIT | 50, // '5'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 147, FT_CMD_WAIT | 50, // '2'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 174, FT_CMD_WAIT | 50, // '4'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 165, FT_CMD_WAIT | 50, // '3'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 174, FT_CMD_WAIT | 50, // '4'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 262, FT_CMD_WAIT | 50, // '1''
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 247, FT_CMD_WAIT | 50, // '7'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 147, FT_CMD_WAIT | 50, // '2'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 174, FT_CMD_WAIT | 50, // '4'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 165, FT_CMD_WAIT | 50, // '3'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 174, FT_CMD_WAIT | 50, // '4'
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 50, // ' '
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 196, FT_CMD_WAIT | 50, // '5'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 220, FT_CMD_WAIT | 50, // '6'
// FT_CMD_NOTES_ON | 1, FT_CMD_SET_FRQ1 | 196, FT_CMD_WAIT | 50, // '5'
//
// FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 500,
// недо-имперский марш
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 131, FT_CMD_SET_FRQ2 | 131, FT_CMD_WAIT | 10, // '1'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 131, FT_CMD_SET_FRQ2 | 131, FT_CMD_WAIT | 10, // '1'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 131, FT_CMD_SET_FRQ2 | 131, FT_CMD_WAIT | 10, // '1'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 131, FT_CMD_SET_FRQ2 | 131, FT_CMD_WAIT | 10, // '1'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 131, FT_CMD_SET_FRQ2 | 131, FT_CMD_WAIT | 10, // '1'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 131, FT_CMD_SET_FRQ2 | 131, FT_CMD_WAIT | 10, // '1'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 131, FT_CMD_SET_FRQ2 | 131, FT_CMD_WAIT | 10, // '1'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 131, FT_CMD_SET_FRQ2 | 131, FT_CMD_WAIT | 10, // '1'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 131, FT_CMD_SET_FRQ2 | 131, FT_CMD_WAIT | 10, // '1'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 165, FT_CMD_SET_FRQ2 | 165, FT_CMD_WAIT | 10, // '3'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 165, FT_CMD_SET_FRQ2 | 165, FT_CMD_WAIT | 10, // '3'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 165, FT_CMD_SET_FRQ2 | 165, FT_CMD_WAIT | 10, // '3'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 131, FT_CMD_SET_FRQ2 | 131, FT_CMD_WAIT | 10, // '1'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 196, FT_CMD_SET_FRQ2 | 196, FT_CMD_WAIT | 10, // '5'
FT_CMD_WAIT | 10, // '_'
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 165, FT_CMD_SET_FRQ2 | 165, FT_CMD_WAIT | 10, // '3'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 131, FT_CMD_SET_FRQ2 | 131, FT_CMD_WAIT | 10, // '1'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 196, FT_CMD_SET_FRQ2 | 196, FT_CMD_WAIT | 10, // '5'
FT_CMD_WAIT | 10, // '_'
FT_CMD_NOTES_ON | 3, FT_CMD_SET_FRQ1 | 165, FT_CMD_SET_FRQ2 | 165, FT_CMD_WAIT | 10, // '3'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_WAIT | 10, // '_'
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 10, // ' '
FT_CMD_NOTES_OFF | 3, FT_CMD_WAIT | 500,
FT_CMD_STOP
};
static const uint16_t* pc = bytecode;
static const uint16_t* pc = FloppyTrack;
static uint16_t wait = 0;
if (wait == 0) {
while (wait == 0) {
uint16_t cmd = *(pc++);
uint16_t value = cmd & (~FT_CMD_MASK);
switch (cmd & FT_CMD_MASK) {
case FT_CMD_STOP:
pc = bytecode; // просто все начнем сначала
drives[0].setEnable(false);
drives[1].setEnable(false);
break;
if (FloppyStatus == FP_READY) {
pc = FloppyTrack;
wait = 0;
} else if (FloppyStatus == FP_PLAY) {
// байткод для 100bpm, тестовая мелодия
case FT_CMD_NOTES_ON:
if (value & 1) {
drives[0].setEnable(true);
}
if (value & 2) {
drives[1].setEnable(true);
}
break;
case FT_CMD_NOTES_OFF:
if (value & 1) {
if (wait == 0) {
while (wait == 0 && FloppyStatus == FP_PLAY) {
uint16_t cmd = *(pc++);
uint16_t value = cmd & (~FT_CMD_MASK);
switch (cmd & FT_CMD_MASK) {
case FT_CMD_STOP:
pc = FloppyTrack;
drives[0].setEnable(false);
}
if (value & 2) {
drives[1].setEnable(false);
}
break;
FloppyStatus = FP_READY;
break;
case FT_CMD_WAIT:
wait = value;
break;
case FT_CMD_NOTES_ON:
if (value & 1) {
drives[0].setEnable(true);
}
if (value & 2) {
drives[1].setEnable(true);
}
break;
case FT_CMD_SET_FRQ1:
drives[0].setFreq(value);
break;
case FT_CMD_NOTES_OFF:
if (value & 1) {
drives[0].setEnable(false);
}
if (value & 2) {
drives[1].setEnable(false);
}
break;
case FT_CMD_SET_FRQ2:
drives[1].setFreq(value);
break;
case FT_CMD_WAIT:
wait = value;
break;
case FT_CMD_SET_FRQ1:
drives[0].setFreq(value);
break;
case FT_CMD_SET_FRQ2:
drives[1].setFreq(value);
break;
}
}
} else {
wait--;
}
} else {
wait--;
}
}

View File

@ -22,7 +22,7 @@
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
#include "floppy-interface.h"
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
@ -259,6 +259,7 @@ static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
FloppyPutData(Buf, *Len);
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
return (USBD_OK);