Author Topic: Converting an old Roland GR-1 to USB  (Read 14865 times)

0 Members and 1 Guest are viewing this topic.

Offline vampi-the-frogTopic starter

  • Regular Contributor
  • *
  • Posts: 50
  • Country: ro
Re: Converting an old Roland GR-1 to USB
« Reply #25 on: October 01, 2016, 11:28:13 pm »
Well, I've been reading up on USB, and I'm starting to figure out what Device, Configuration, Interface, Endpoint and other concepts mean, and after looking at the descriptor dumps from some USB devices I found lying around, I realized all I need to do is copy the descriptors from an existing device, such as this Alesis io2 Express card that I own, which has both audio and MIDI. Then I just need to do a packet dump while recording, and duplicate the structure of the packets on my device side.

So that's kind of clear for now, however my main problem is still all the code noise for the STM32. Just so many fucking versions of the same code doing the same thing, and so many IDEs doing the same thing, each in a different way, and always generating some error or other, what a fucking nightmare. Whenever you find an example or tutorial, it uses code from 2008 or something, and you have to make sense of the libraries they had back then in order to just get an interrupt or something. How do I even send a string back to the computer? I just want to get some status updates from my code.

And why is everyone trying to sell me something? The IDEs are either limited or have a paid version, everything seems to cost extra money. Jeez, I got these dev boards because they were cheap, not because I wanted to spend hundreds of bucks on stupid software.

Anyway, I'm now trying to figure out how to use gcc to compile, since it seems the only option I can understand - I can write a Makefile and do everything by hand.

EDIT 1: It seems one working combination is Linux + STM32CubeMX + CubeMX2Makefile + gcc-arm-embedded + stlink + gdb for debugging. Now to see how to get some strings sent back from the device (ie printf). These might work on windows as well, but I am not very much interested in that.

EDIT 2: Instead of stlink, I am now using OpenOCD for flashing and debugging. It also took me 2 days to discover that in CubeMX you need to mark the SWD pins as SWD pins, and not leave them unused, otherwise debug won't work, and flashing won't work unless you hold down reset. I've also discovered how to make custom board files for CubeMX, it's just a bunch of XML. I am also using semihosting, so I can get printf() output back on the PC, so now I'm debugging the USB device code, to see what I can do to make it show as an USB device.
« Last Edit: October 05, 2016, 07:02:57 am by vampi-the-frog »
 

Offline vampi-the-frogTopic starter

  • Regular Contributor
  • *
  • Posts: 50
  • Country: ro
Re: Converting an old Roland GR-1 to USB
« Reply #26 on: October 05, 2016, 05:01:25 pm »
Right. I now am the proud owner of a Rigol DS1054Z.

I've measured the DAC I2S signal more precisely:

- The input to CLK is 50 pulses at 3.2MHz
- The input to SI/LSI is random pulses, I assume this is the quiet data when no sound is being synthesized.
- The input to LRCK is 64kHz, but jittery
- The input to LRSEL/RSI is +5V



 

Offline vampi-the-frogTopic starter

  • Regular Contributor
  • *
  • Posts: 50
  • Country: ro
Re: Converting an old Roland GR-1 to USB
« Reply #27 on: October 05, 2016, 05:42:27 pm »
Some more scope screens. It seems there's a consistency to the LR clock jitter, I don't really understand it. There's a screen with averaging on, and one with high res (see upper right).

Most puzzling is the fact that on the top right it says 64kHz, and on the bottom it says 62.5kHz. Which is it? Is the jitter making the transition from 62.5 to 64? What is up with that? I'm new to this scope, so I'm not sure which reading means what.

The second to last one is one of the pins of the 20MHz crystal.

EDIT: Ok, so I figured it out. There are two pulses on the LRCK line, so if you skip a pulse, it's 32kHz. With a trigger holdoff of 30us, it seems to trigger properly now, without screen jitter. In the last screenshot you can see how they are unevenly spaced, but eventually line up to 32kHz. According to the datasheet, I see one swing of LRCK means one sample on one channel, so two pulses of LRCK means 2 stereo samples. I suppose the jitter is small enough so that no audio artifacts are heard, but there you go. Anyway, I hope it's some sort of hardware design fault, and in reality it was meant to be non-jittered, so when I do manage to stream the data to the PC, it will be perfectly aligned and crystal clear.
« Last Edit: October 05, 2016, 06:10:24 pm by vampi-the-frog »
 

Offline vampi-the-frogTopic starter

  • Regular Contributor
  • *
  • Posts: 50
  • Country: ro
Re: Converting an old Roland GR-1 to USB
« Reply #28 on: October 07, 2016, 11:12:29 pm »
Sorry to be turning this thread into a development log, but here we go.

Here are some more scope screenshots.

It also seems that the sample rate is actually 64000 instead of 32000. However, it's a non standard sampling rate, so I'll go with either 32000 and skip every other sample, or 96000 and double every second sample. I can then losslessly downsample the recordings.

I'm still figuring out how the data pins work. You can see on the scope the 3 pins and on the bottom part, it's the analog output. I'm not sure where the noise is coming from, but it's really zoomed in so I could see the steps. On a real analog scope, you can actually see the sample points.

If it is I²S, then it's a strange variation. The controller I'm using are STM32F103RBT6, which doesn't have I²S. However, the STM32F103xC series does, and I've ordered a few, but I'm thinking I should be able to do this with just GPIO. Maybe. Maybe not, I dunno.

Anyway, I managed to get STM32CubeMX to generate a proper USB Audio project, and now after I compile the generated code, the computer recognizes the dev board as a USB sound device with whatever VID and PID I chose. I'm happy about that ^^

It seems to only have a playback interface or feature or whatever it's called, not a recording one, and no mixing except mute.

Also, I've taken a look inside my Roland GR-20, and it seems to have a 32000Hz sampling rate as well, but it has 3 DACs. I'm not sure what they do, perhaps we'll take a look at those as well as the next project.

As long as I'm rambling on, my next idea is to make a custom USB sound card, with a motorized potentiometer for volume, and mute and also multimedia keys. That would be sweet.
 

Offline vampi-the-frogTopic starter

  • Regular Contributor
  • *
  • Posts: 50
  • Country: ro
Re: Converting an old Roland GR-1 to USB
« Reply #29 on: October 12, 2016, 10:03:02 pm »
I've managed to duplicate the configuration descriptor from a working sound card, with sound out + in and MIDI out + in. I captured with Wireshark and copied the data in the comments below, and then fixed it up by hand and used lsusb -v for more info as well. Aparently wireshark doesn't know about the MIDI streaming descriptors, but lsusb does. It is possible to write a tool that generates the C code, probably using libusb, but this time I did it by hand.

Next up is to duplicate the rest of the USB packets that are sent back to the host, by using wireshark to capture the USB packets to and from the working sound card, and doing the same thing in my STM32 code.

I've also managed to get a decent workflow with a ST-LINK v2 programmer, make, openocd and gdb.



Here is my array:

Code: [Select]
#define AUDIO_SAMPLE_FREQ(frq) \
(uint8_t)(frq), \
(uint8_t)((frq >> 8)), \
(uint8_t)((frq >> 16))

#define AUDIO_PACKET_SZE(frq) \
(uint8_t)(((frq * 2 * 2)/1000) & 0xFF), \
(uint8_t)((((frq * 2 * 2)/1000) >> 8) & 0xFF)

#define FIELD_UINT16(a) (uint8_t)a, (uint8_t)(a >> 8)

#define FIELD_BCD(a, b) (uint8_t)b, (uint8_t)a

/* USB AUDIO device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_AUDIO_CfgDesc[USB_AUDIO_CONFIG_DESC_SIZ] __ALIGN_END = {
    // CONFIGURATION DESCRIPTOR
    9,                  // bLength
    0x02,               // bDescriptorType (CONFIGURATION)
    FIELD_UINT16(255),  // wTotalLength
    4,                  // bNumInterfaces
    1,                  // bConfigurationValue
    0,                  // iConfiguration
    0x80,               // Configuration bmAttributes:
                        // 1... .... = Must be 1: Must be 1 for USB 1.1 and higher
                        // .0.. .... = Self-Powered: This device is powered from the USB bus
                        // ..0. .... = Remote Wakeup: This device does NOT support remote wakeup
    250,                // bMaxPower (500mA)

    // INTERFACE DESCRIPTOR (0.0): class Audio
    9,                  // bLength
    0x04,               // bDescriptorType (INTERFACE)
    0,                  // bInterfaceNumber
    0,                  // bAlternateSetting
    0,                  // bNumEndpoints
    0x01,               // bInterfaceClass: Audio
    0x01,               // bInterfaceSubClass
    0x00,               // bInterfaceProtocol
    0,                  // iInterface

    // Class-specific Audio Control Interface Descriptor: Header Descriptor
    11,                 // bLength
    0x24,               // bDescriptorType (audio class interface)
    0x01,               // Subtype: Header Descriptor
    FIELD_BCD(1, 00),   // Version: 1,00
    FIELD_UINT16(53),   // Total length
    3,                  // Total number of interfaces
    1,                  // Interface number
    2,                  // Interface number
    3,                  // Interface number

    // Class-specific Audio Control Interface Descriptor: Input terminal descriptor
    12,                 // bLength
    0x24,               // bDescriptorType (audio class interface)
    0x02,               // Subtype: Input terminal descriptor
    1,                  // bTerminalID
    FIELD_UINT16(0x101),// wTerminalType  USB Streaming
    0,                  // bAssocTerminal
    2,                  // bNrChannels
    FIELD_UINT16(3),    // wChannelConfig
                        // Left Front (L)
                        // Right Front (R)
    0,                  // iChannelNames 
    0,                  // iTerminal 


    // Class-specific Audio Control Interface Descriptor: Output terminal descriptor
    9,                  // bLength
    0x24,               // bDescriptorType (audio class interface)
    0x03,               // Subtype: Output terminal descriptor
    2,                  // bTerminalID
    FIELD_UINT16(0x301),// wTerminalType  Speaker
    0,                  // bAssocTerminal
    1,                  // bSourceID
    0,                  // iTerminal 

    // Class-specific Audio Control Interface Descriptor: Input terminal descriptor
    12,                 // bLength
    0x24,               // bDescriptorType (audio class interface)
    0x02,               // Subtype: Input terminal descriptor
    3,                  // bTerminalID
    FIELD_UINT16(0x201),// wTerminalType  Microphone
    0,                  // bAssocTerminal
    2,                  // bNrChannels
    FIELD_UINT16(0x0003),// wChannelConfig
                        //Left Front (L)
                        //Right Front (R)
    0,                  // iChannelNames 
    0,                  // iTerminal 

    // Class-specific Audio Control Interface Descriptor: Output terminal descriptor
    9,                  // bLength
    0x24,               // bDescriptorType (audio class interface)
    0x03,               // Subtype: Output terminal descriptor
    4,                  // bTerminalID
    FIELD_UINT16(0x101),// wTerminalType  USB Streaming
    0,                  // bAssocTerminal
    3,                  // bSourceID
    0,                  // iTerminal 

    // INTERFACE DESCRIPTOR (1.0): class Audio
    9,                  // bLength
    0x04,               // bDescriptorType (INTERFACE)
    1,                  // bInterfaceNumber
    0,                  // bAlternateSetting
    0,                  // bNumEndpoints
    0x01,               // bInterfaceClass: Audio
    0x02,               // bInterfaceSubClass
    0x00,               // bInterfaceProtocol
    0,                  // iInterface

    // INTERFACE DESCRIPTOR (1.1): class Audio
    9,                  // bLength
    0x04,               // bDescriptorType (INTERFACE)
    1,                  // bInterfaceNumber
    1,                  // bAlternateSetting
    1,                  // bNumEndpoints
    0x01,               // bInterfaceClass: Audio
    0x02,               // bInterfaceSubClass
    0x00,               // bInterfaceProtocol
    0,                  // iInterface

    // Class-specific Audio Streaming Interface Descriptor: General AS Descriptor
    7,                  // bLength
    0x24,               // bDescriptorType (audio class interface)
    0x01,               // Subtype: General AS Descriptor
    1,                  // Terminal ID
    0,                  // Interface delay in frames
    FIELD_UINT16(1),    // Format

    // Class-specific Audio Streaming Interface Descriptor: Format type descriptor
    14,                 // bLength
    0x24,               // bDescriptorType (audio class interface)
    0x02,               // Subtype: Format type descriptor
    1,                  // bFormatType  (FORMAT_TYPE_I)
    2,                  // bNrChannels
    3,                  // bSubframeSize
    24,                 // bBitResolution
    2,                  // bSamFreqType  Discrete
    AUDIO_SAMPLE_FREQ(44100),
    AUDIO_SAMPLE_FREQ(48000),

    // ENDPOINT DESCRIPTOR
    9,                  // bLength
    0x05,               // bDescriptorType (ENDPOINT)
    0x01,               // bEndpointAddress OUT  Endpoint:1
                        // 0... .... = Direction: OUT Endpoint (0x01)
                        // .... 0001 = Endpoint Number (0x01)
    0x09,               // bmAttributes
                        // .... ..01 = Transfertype: Isochronous-Transfer
                        // .... 10.. = Synchronisationtype: Adaptive (0x02)
                        // ..00 .... = Behaviourtype: Data-Endpoint (0x00)
    FIELD_UINT16(288),  // wMaxPacketSize
                        // ...0 0... .... .... = Transactions per microframe: 1
                        // .... ..01 0010 0000 = Maximum Packet Size (288)
    1,                  // bInterval
    0,
    0,

    // Class-specific Audio Streaming Endpoint Descriptor
    7,                  // bLength
    0x25,               // bDescriptorType (audio class endpoint)
    0x01,               // Subtype
    0x01,               // bmAttributes
                        //Sampling Frequency
    0,                  // bLockDelayUnits  Undefined
    FIELD_UINT16(0),    // wLockDelay  Undefined


    // INTERFACE DESCRIPTOR (2.0): class Audio
    9,                  // bLength
    0x04,               // bDescriptorType (INTERFACE)
    2,                  // bInterfaceNumber
    0,                  // bAlternateSetting
    0,                  // bNumEndpoints
    0x01,               // bInterfaceClass: Audio
    0x02,               // bInterfaceSubClass
    0x00,               // bInterfaceProtocol
    0,                  // iInterface

    // INTERFACE DESCRIPTOR (2.1): class Audio
    9,                  // bLength
    0x04,               // bDescriptorType (INTERFACE)
    2,                  // bInterfaceNumber
    1,                  // bAlternateSetting
    1,                  // bNumEndpoints
    0x01,               // bInterfaceClass: Audio
    0x02,               // bInterfaceSubClass
    0x00,               // bInterfaceProtocol
    0,                  // iInterface

    // Class-specific Audio Streaming Interface Descriptor: General AS Descriptor
    7,                  // bLength
    0x24,               // bDescriptorType (audio class interface)
    0x01,               // Subtype: General AS Descriptor
    4,                  // Terminal ID
    0,                  // Interface delay in frames
    FIELD_UINT16(1),    // Format

    // Class-specific Audio Streaming Interface Descriptor: Format type descriptor
    14,                 // bLength
    0x24,               // bDescriptorType (audio class interface)
    0x02,               // Subtype: Format type descriptor
    1,                  // bFormatType  (FORMAT_TYPE_I)
    2,                  // bNrChannels
    3,                  // bSubframeSize
    24,                 // bBitResolution
    0,                  // bSamFreqType  Continuous
    AUDIO_SAMPLE_FREQ(44100), // tLowerSamFreq
    AUDIO_SAMPLE_FREQ(48000), // tUpperSamFreq

    // ENDPOINT DESCRIPTOR
    9,                  // bLength
    0x05,               // bDescriptorType (ENDPOINT)
    0x82,               // bEndpointAddress IN  Endpoint:2
                        // 1... .... = Direction: IN Endpoint (0x01)
                        // .... 0010 = Endpoint Number (0x02)
    0x05,               // bmAttributes
                        // .... ..01 = Transfertype: Isochronous-Transfer
                        // .... 01.. = Synchronisationtype: Asynchronous (0x01)
                        // ..00 .... = Behaviourtype: Data-Endpoint (0x00)
    FIELD_UINT16(291),  // wMaxPacketSize
                        // ...0 0... .... .... = Transactions per microframe: 1 (0)
                        // .... ..01 0010 0011 = Maximum Packet Size (291)
    1,                  // bInterval
    0,                  // bRefresh
    0,                  // bSynchAddress

    // AudioControl Endpoint Descriptor
    7,                  // bLength
    0x25,               // bDescriptorType (audio class endpoint)
    0x01,               // Subtype
    0x00,               // bmAttributes
    0,                  // bLockDelayUnits  Undefined
    FIELD_UINT16(0),    // wLockDelay  Undefined

    // INTERFACE DESCRIPTOR (3.0): class Audio
    9,                  // bLength
    0x04,               // bDescriptorType (INTERFACE)
    3,                  // bInterfaceNumber
    0,                  // bAlternateSetting
    2,                  // bNumEndpoints
    0x01,               // bInterfaceClass: Audio
    0x03,               // bInterfaceSubClass
    0x00,               // bInterfaceProtocol
    0,                  // iInterface

    // MIDIStreaming Interface Descriptor
    7,                  // bLength
    0x24,               // bDescriptorType (unknown)
    1,                  // bDescriptorSubtype  (HEADER)
    FIELD_BCD(1, 00),   // bcdADC .00
    FIELD_UINT16(65),   // wTotalLength

    // MIDIStreaming Interface Descriptor
    6,                   // bLength
    0x24,                // bDescriptorType (unknown)
    2,                   // bDescriptorSubtype  (MIDI_IN_JACK)
    1,                   // bJackType  Embedded
    1,                   // bJackID
    0,                   // iJack 

    // MIDIStreaming Interface Descriptor
    6,                   // bLength
    0x24,                // bDescriptorType (unknown)
    2,                   // bDescriptorSubtype  (MIDI_IN_JACK)
    2,                   // bJackType  External
    2,                   // bJackID
    0,                   // iJack 

    // MIDIStreaming Interface Descriptor
    9,                   // bLength
    0x24,                // bDescriptorType (unknown)
    3,                   // bDescriptorSubtype  (MIDI_OUT_JACK)
    1,                   // bJackType  Embedded
    3,                   // bJackID
    1,                   // bNrInputPins
    2,                   // baSourceID( 0) 2
    1,                   // BaSourcePin( 0) 1
    0,                   // iJack 

    // MIDIStreaming Interface Descriptor
    9,                   // bLength
    0x24,                // bDescriptorType (unknown)
    3,                   // bDescriptorSubtype  (MIDI_OUT_JACK)
    2,                   // bJackType  External
    4,                   // bJackID
    1,                   // bNrInputPins
    1,                   // baSourceID( 0) 1
    1,                   // BaSourcePin( 0) 1
    0,                   // iJack 

    // ENDPOINT DESCRIPTOR
    9,                  // bLength
    0x05,               // bDescriptorType (ENDPOINT)
    0x03,               // bEndpointAddress OUT  Endpoint:3
                        // 0... .... = Direction: OUT Endpoint (0x02)
                        // .... 0011 = Endpoint Number (0x03)
    0x02,               // bmAttributes
                        // .... ..10 = Transfertype: Bulk-Transfer
    FIELD_UINT16(16),   // wMaxPacketSize
                        // .... ..00 0001 0000 = Maximum Packet Size (16)
    0,                  // bInterval
    0,                  // bRefresh
    0,                  // bSynchAddress

    // MIDIStreaming Endpoint Descriptor
    5,                  // bLength
    0x25,               // bDescriptorType (unknown)
    1,                  // bDescriptorSubtype  (GENERAL)
    1,                  // bNumEmbMIDIJack
    1,                  //    baAssocJackID( 0)       1

    // ENDPOINT DESCRIPTOR
    9,                  // bLength
    0x05,               // bDescriptorType (ENDPOINT)
    0x84,               // bEndpointAddress IN  Endpoint:4
                        // 1... .... = Direction: IN Endpoint (0x02)
                        // .... 0100 = Endpoint Number: 0x04
    0x02,               // bmAttributes
                        // .... ..10 = Transfertype: Bulk-Transfer (0x02)
    FIELD_UINT16(16),   // wMaxPacketSize
                        // .... ..00 0001 0000 = Maximum Packet Size
    0,                  // bInterval
    0,                  // bRefresh
    0,                  // bSynchAddress

    // MIDIStreaming Endpoint Descriptor
    5,                  // bLength
    0x25,               // bDescriptorType (unknown)
    1,                  // bDescriptorSubtype  (GENERAL)
    1,                  // bNumEmbMIDIJack
    3                   // baAssocJackID(0)
};
« Last Edit: October 12, 2016, 10:06:06 pm by vampi-the-frog »
 

Offline vampi-the-frogTopic starter

  • Regular Contributor
  • *
  • Posts: 50
  • Country: ro
Re: Converting an old Roland GR-1 to USB
« Reply #30 on: October 16, 2016, 09:00:28 pm »
I have switched over to libopencm3 and I've already gotten USB MIDI to work. Now to add the USB Audio Streaming stuff in there.
 

Offline vampi-the-frogTopic starter

  • Regular Contributor
  • *
  • Posts: 50
  • Country: ro
Re: Converting an old Roland GR-1 to USB
« Reply #31 on: October 22, 2016, 11:11:57 am »
Hooray! After adding the USB Audio Streaming descriptors to my code, and setting up the isochronous endpoint, I struggled to figure out how to use the libopencm3 functions, but finally figured it out, and now I've managed to actually get data from the device into the computer, by recording a wav file with
Code: [Select]
arecord -D hw:1,0,0 -c 2 -f S16_LE -r 96000 -d 1 foo.wav
The wav file looks like a series of consecutive incrementing values:

Code: [Select]
00000000  52 49 46 46 24 dc 05 00  57 41 56 45 66 6d 74 20  |RIFF$...WAVEfmt |
00000010  10 00 00 00 01 00 02 00  00 77 01 00 00 dc 05 00  |.........w......|
00000020  04 00 10 00 64 61 74 61  00 dc 05 00 34 00 35 00  |....data....4.5.|
00000030  36 00 37 00 38 00 39 00  3a 00 3b 00 3c 00 3d 00  |6.7.8.9.:.;.<.=.|
00000040  3e 00 3f 00 40 00 41 00  42 00 43 00 44 00 45 00  |>.?.@.A.B.C.D.E.|
00000050  46 00 47 00 48 00 49 00  4a 00 4b 00 4c 00 4d 00  |F.G.H.I.J.K.L.M.|
00000060  4e 00 4f 00 50 00 51 00  52 00 53 00 54 00 55 00  |N.O.P.Q.R.S.T.U.|
00000070  56 00 57 00 58 00 59 00  5a 00 5b 00 5c 00 5d 00  |V.W.X.Y.Z.[.\.].|
00000080  5e 00 5f 00 40 00 00 00  80 00 08 88 00 01 04 00  |^._.@...........|
00000090  c0 00 00 88 40 01 80 01  a8 bb b1 9f b2 da ac cb  |....@...........|

And the code looks like this:

Code: [Select]
int sending_iso = 0;
uint16_t audio_buf[96 * 2];
static void send_audiobuf(usbd_device *usbd_dev) {
int i;
for(i = 0; i < 96 * 2; i++) audio_buf[i] = i;
usbd_ep_write_packet(usbd_dev, 0x2, audio_buf, sizeof(audio_buf));
}

static void usbaudio_data_tx_cb(usbd_device *usbd_dev, uint8_t ep) {
if(ep == 2 && sending_iso) {
printf("usbaudio ep %p, %d tx\n", usbd_dev, ep);
send_audiobuf(usbd_dev);
}
}

int usbaudio_control_callback(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, usbd_control_complete_callback *complete) {
(void)buf;
(void)len;
printf("control_callback %p %02x %02x %02x\n", usbd_dev, req->bmRequestType, req->bRequest, req->wValue);
if((req->bmRequestType & 0x01) && req->bRequest == 0x0b) {
if(req->wValue == 1) {
// Begin sending isochronous data
sending_iso = 1;
printf("start sending iso\n");
} else {
sending_iso = 0;
printf("stop sending iso\n");
}
}
return 1;
}

whereas the callbacks are initialized thusly:

Code: [Select]
usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_ISOCHRONOUS, 96 * 2 * 2, usbaudio_data_tx_cb);

usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
usbaudio_control_callback);

My problem next was how does the host select the samplerate, because in my case I have many sample rates:

Code: [Select]
#define AUDIO_SAMPLE_FREQ(frq) \
{ (uint8_t)(frq), (uint8_t)(((frq) >> 8)), (uint8_t)(((frq) >> 16)) }

static const struct {
struct usb_audio_streaming_header_descriptor header;
struct usb_audio_streaming_format_type_descriptor format_type;
uint8_t freq[4][3];
} __attribute__((packed)) audio_streaming_functional_descriptors = {
.header = {
.bLength = 7,
.bDescriptorType = 0x24,
.bDescriptorSubtype = 0x01,
.bTerminalID = 4,
.bInterfaceDelay = 0,
.wFormat = 1
},
.format_type = {
.bLength = 20,
.bDescriptorType = 0x24,
.bDescriptorSubtype = 0x02,
.bFormatType = 1,
.bNrChannels = 2,
.bSubframeSize = 2,
.bBitResolution = 16,
.bSamFreqType = 4
},
.freq = {
AUDIO_SAMPLE_FREQ(32000),
AUDIO_SAMPLE_FREQ(48000),
AUDIO_SAMPLE_FREQ(64000),
AUDIO_SAMPLE_FREQ(96000)
}
};

I have tried recording with another, working sound card that can do 48000 and 44100, but besides the SET INTERFACE request, there is no other data sent to it to select the sample rate. I found that quite strange. However, another USB sound interface that I own (08bb:2902 Texas Instruments PCM2902 Audio Codec) cleared up what I need to do - I need to have an interface descriptor with a different bAlternateSetting for each of the sample rates, each with its own endpoint.

So that's up next, and then figuring out how to get the data from the DAC, because the signal coming into it seems similar to I2S, but it has a strange delay, so I think I'll just do it somehow from software, perhaps with interrupts. Besides, even if it was I2S, the STM32F103RBT6, which is what is on the Olimex board, does not have support for it. I have ordered a couple of STM32RCT6's, but I am still waiting for a hot air station to arrive, so I can exchange them. They're pin compatible, and the C one has I2S.
 

Offline Cervisia

  • Regular Contributor
  • *
  • Posts: 83
  • Country: 00
Re: Converting an old Roland GR-1 to USB
« Reply #32 on: October 22, 2016, 01:35:34 pm »
Quote
the signal coming into it seems similar to I²S, but it has a strange delay

I²S has a  delay: the MSB is transmitted one clock after the L/R transiton. If the format is not I²S but left-justified, there is no delay.
 

Offline vampi-the-frogTopic starter

  • Regular Contributor
  • *
  • Posts: 50
  • Country: ro
Re: Converting an old Roland GR-1 to USB
« Reply #33 on: October 22, 2016, 09:31:53 pm »
Quote
the signal coming into it seems similar to I²S, but it has a strange delay

I²S has a  delay: the MSB is transmitted one clock after the L/R transiton. If the format is not I²S but left-justified, there is no delay.

In my case it seems it's two clocks somehow.

 

Offline vampi-the-frogTopic starter

  • Regular Contributor
  • *
  • Posts: 50
  • Country: ro
Re: Converting an old Roland GR-1 to USB
« Reply #34 on: October 26, 2016, 09:03:35 am »
I've managed to get recording to work properly on linux, with 5 alternate settings for the audio streaming interface - one for idle (zero bandwidth) and one for each of 32000, 48000, 64000 and 96000 sampling frequencies. These might come in handy later. I struggled with a hard fault for a while, which turned out to be due to a small control buffer (the buffer was 128 bytes and the configuration descriptor went way above 128 when I added the extra alternate settings).

So now I've managed to record at all of those frequencies, and next up is figuring out the I2S stuff, and replacing the F103RBT6 with a F105RBT6, which has 96kHz I2S, unless I'm mistaking when reading the datasheet.

One problem, though, is that windows won't recognize the device, it says it can't start it. I guess I'll have to figure something out to fix that, cause windows is where I want to use it.
 

Offline vampi-the-frogTopic starter

  • Regular Contributor
  • *
  • Posts: 50
  • Country: ro
Re: Converting an old Roland GR-1 to USB
« Reply #35 on: December 13, 2016, 07:49:49 pm »
I've finally received a new hot air station, branded "YOUYUE 858 D+" with full Chinglish manual. I was able to replace the F103 with a F105, which has a different USB core (OTG), and two I2S modules. I'm now in the process of porting my code to this new chip.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf