Converting an old Roland GR-1 to USB - Page 1
Forum section: electronics / projects

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: September 10, 2016, 12:56:59 pm
content: Hey gang, I've recently got a second hand Roland MIDI guitar pickup (GK-2) and a GR-1 processor which does a couple of things - converts the analog output of the pickup (which is just 6 small humbucker pickups, one for each string) to MIDI messages, and also has a synthesizer inside of it. It only has analog outputs for the synthesized audio, and only MIDI DIN-5 connectors for the MIDI data.I'd like to add an USB port to it, with some micro which would take the digital audio from before the DAC (uPD6376GS), and announce itself as a USB sound card and MIDI device. There is a tiny bit of space left on the back pannel for a USB type B port.Anyway, my question is how would I do this with least hardware hassle - ie, choose a small board with the USB port on it, maybe an Arduino or derivative (I've successfully used a Pololu A-star 32U4 for USB MIDI before), wire LRCK, CLK and SI/LSI from the DAC, and then the MIDI stuff as well, then after the wiring is done, I can just code the firmware. There's +5V available, but also +7V and -7V, so perhaps I can skip the power supply part. I'd also like to use a USB type B instead of microUSB, simply because it's physically more robust, or at least I feel like it is.I don't know the frequency of the clock pin yet, the datasheet says something about 400khz max for the DAC, but it's likely around 44100 Hz. The synthesis chip uses a ROM for the samples, so I'm thinking they'd be using a limited sample rate just to efficiently use the space.GR-1 Service Manual:https://www.dropbox.com/s/dw4ou57kfz9wvqd/ROLAND_GR-1_SERVICE_NOTES.pdf?dl=0GR-1 Owner's Manual:https://www.dropbox.com/s/qbidxhtcaor5sng/GR-1_OM.pdf?dl=0uPD6376GS datasheet:https://www.dropbox.com/s/cyhon0aq1s6okph/uPD6376GS.pdf?dl=0GK-2 Owner's Manual:https://www.dropbox.com/s/80i6ngj6s5t5s1q/GK-2_OM.pdf?dl=0Here is the DAC:Here is the MIDI stuff:Here's the back of the thing, with a mark where I think the USB port would fit:Ports are DC IN 9V/1.5A, power switch, MIDI OUT, MIDI IN, GK-2 13-pin input, Volume pedal input, custom pedal input (these are both just foot pedals with potentiometers, afaik), guitar out (simply takes the regular guitar output so you only use one cable), guitar return L and R, MIX OUT R and L/mono, phones.

author: Buriedcode
author_rank: Super Contributor
timestamp: September 10, 2016, 04:08:15 pm
content: No replies? I'll give it a bashAs you may have guessed by googling, USB audio is a hotly debated topic - mostly because of unrealistic expectations (latency) from 'audiophiles' and the bad reputation of very low end products. But it can be done, either with a stock 'chip that does it for you', or using a micro with a USB peripheral and I2S capability. The CM108 by 'C-media' is cheap, cheerful, and does the job. I haven't seen these devices available to buy from distributors, but so many cheap 'USB soundcard' plug in dongles are based on it you can pick these up from Amazon for $2:https://www.amazon.co.uk/Dynamode-USB-2-0-Sound-Card/dp/B0010JP9CYIt accepts I2S but specifically at either 48kHz or 44.1kHz (the chip has on board PLL to convert the 12MHz used for USB to 12.288/11.2896). Datasheet here:http://www.qsl.net/om3cph/sb/CM108_DataSheet_v1.6.pdfA quick fudge would be to just wire the audio out of your MIDI thing to the audio in (re-sampling using its build-in ADC), but depending on the sample rate of the DAC, if they match you should be able to just hooked it up with I2S.As for having MIDI *and* audio via the same USB, I haven't seen any devices that will do that for you, so you will have to roll your own. There are app notes from ST and microchip on how to do this using the STM32, and PIC32 but it is very involved - I spent a month in my spare time making a half decent USB ADC/DAC from a PIC24 using asynchronous transport, mostly because windows drivers only like to use isochronous. USB audio also uses up quite a bit of USB bandwidth, mostly because it's real-time, so cannot have large buffers. The same goes for MIDI, the actual through-put isn't that much, but to reduce the latency to a low level (<30ms) you have to send small packets regularly, which isn't an efficient use of the bus.Another cheapy way to do it would be to use a MIDI - USB converter, and a audio-USB (like the one linked above) and have a cheap 4-port USB hub. Effectively meaning you have one USB cable, with two devices. Its not an elegant solution, but would still be rather small, perhaps able to fit into the housing and its also rather cheap.I suspect you will have latency issues whatever you do, I remember a friend had one of these and there was noticeable latency between plucking a string and a 'sound' being made, add to that the 10-50ms from USB, soundcard playback latency etc.. and it can get annoying.Hopefully some food for thought!

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: September 10, 2016, 04:55:00 pm
content: From the CM108 datasheet, it does seem it has very similar input pins for the serial data, ADSCLK (ADC I2S Serial Clock), ADLRCK (ADC I2S Left / Right Clock) and SDIN (ADC I2S Data Input). I'll have to measure the actual sample rate somehow. The GR-1 service manual doesn't seem to say anything about its value. The chip that feeds the DAC has a 20MHz clock input, so I'm thinking it's going to be a subdivision of that.Food for thought indeed.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: September 13, 2016, 09:19:53 pm
content: I am looking at Arduino Teensy, it seems to have a powerful enough controller, and it just might be enough for my needs. So, a record-only sound card, with an unknown sample rate (I estimate about 25kHz or 32kHz, haven't been able to measure yet), and MIDI in and out ports, both on USB. I also like the look ofthis olimex board, simply because of the USB type B port.There's also a dev library for USB devices, STM32Cube, which seems to make it easy to code such things.Also,Anyone experienced with this?

author: Someone
author_rank: Super Contributor
timestamp: September 14, 2016, 12:19:52 am
content: Quote from: vampi-the-frog on September 13, 2016, 09:19:53 pmThe sample rate will be your problem, almost all "sound cards" want to be the master clock. Trying to synchronise software with the internal word clock of an arbitrary device (your GR-1 here) is quite a challenge, or you'll need use an asynchronous sample rate convertor to allow both devices to run at their own sample rates.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: September 14, 2016, 06:08:27 am
content: If you want to do a custom job then perhaps the Cypress PSoC5 is something you want to look at. The dev-board is only about 10$...I have the Roland VG-99 ;-)

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: September 14, 2016, 07:03:31 am
content: Quote from: Someone on September 14, 2016, 12:19:52 amCan you elaborate on that a bit please?I was thinking I could use the DAC's clock as an interrupt, then build a buffer and send it when it's full. I don't care if there's much latency at this point, I just want the digital data.Quote from: obiwanjacobi on September 14, 2016, 06:08:27 amQuite interesting dev board. It really looks like I'll have to get a bunch of them and experiment.Really nice gear too! I'd like to get the Boss GP-10 too when I can afford it, it seems to have similar functionality to VG-99. Can you record audio + MIDI through the USB port?

author: casinada
author_rank: Frequent Contributor
timestamp: September 14, 2016, 07:22:50 am
content: May be you should try to get one of the Midi to USB adapters:http://www.m-audio.com/products/view/midisport-1x1http://www.m-audio.com/products/view/uno

author: obiwanjacobi
author_rank: Super Contributor
timestamp: September 14, 2016, 07:34:42 am
content: Quote from: vampi-the-frog on September 14, 2016, 07:03:31 amNot sure about MIDI, butI have recordedfrom it over USB. I would be really surprised if MIDI wouldn't work over USB.I am not familiar with the Boss GP-10 - it looks more for live playing and VG-99 is (IMO) more for studio work.

author: Buriedcode
author_rank: Super Contributor
timestamp: September 14, 2016, 04:38:21 pm
content: There's several grey areas here that I think need to be cleared up. Firstly, just sending bytes, that just so happen to be digital audio samples, over USB, isn't the same as USB audio. If you want your PC/mac to pick the USB devices up as an audio device, then it needs to enumerate as such and adhere to certain restrictions that will govern how it works - including sample rate, bit depth, feedback endpoints to tell the PC how many samples its sending (so it can calculate the sample rate, and convert it to your playback sample rate accordingly).Similarly a MIDI device, if you want your apps to pick up the midi messages, must be a USB MIDI device class. One can of course have several devices on one bus, but is very involved.If your goal is just to use USB to 'get data' from it, then you can indeed use a teensy/STM32 to read bytes from the I2S, and a UART for the MIDI, and just package them up and send them over USB as a HID device - but that won't help at the other end, its just 'bytes'. You could easily write an application that picks up these bytes, and writes to a *wav and a MIDI file but they will only be available after you've stopped recording.Apologies if I was wrong in my reply, I had assumed you wanted to make something that means when you plug it into your PC via USB, it appears as both an audio device (a recording device) and a MIDI device (for using VST plugins, cubase, logic pro etc..). I have seen both DIY USB soundcards, and DIY USB MIDI interfaces, but not a project that merges the two. It can of course be done, one can buy interfaces with audio in/out and MIDI in/out in one box, but they're about £110-150.

author: MosherIV
author_rank: Super Contributor
timestamp: September 14, 2016, 05:12:19 pm
content: +1 to what Buriedcode saidQuoteA suitable STM32 can do what you want but there will be an awful lot of code to put together.ST do provide sample code/project for direct audio sampling via built in ADCI am not aware of any sample code/project for MIDI from ST or other.ST do provide a sample project for USB Composite device, that is a USB device with more than 1 USB endpoint device.ST do provide a sample project for USB Audio but NOT MIDI.I do not know where the I2S came into the conversation, but again STM32 can do I2S, it is buried in the SPI controller I think.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: September 14, 2016, 05:29:04 pm
content: It looks like STM32Cube supports theUSB Audio class(page 43), so that's what I'm planning to use.I can't figure out whether I need a programmer for theSTM32-H103, or if I can just use the USB port for programming it. Anyway, the JTAG programmer costs more than the dev boardso I'm trying to figure out how to program it.It's ok if I can't do the MIDI part, I can use a separate usb to MIDI cheapy device, but it would be cool if I can do both.EDIT: there are USB MIDI libraries for Arduino, and they lookprettythin. I'm a programmer in real life, so coding the USB MIDI part is not really an issue.Also, nice cleanly recorded song, obi.

author: MosherIV
author_rank: Super Contributor
timestamp: September 14, 2016, 07:22:41 pm
content: Yes, it looks like the Olimex board requires a Jtag debugger/programmer.Try looking at the St Discovery or Disco range of dev/eval boards.They have on board St-link debugger/programmer and they are amazingly cheap.http://www.st.com/content/st_com/en/products/evaluation-tools/product-evaluation-tools/mcu-eval-tools/stm32-mcu-eval-tools/stm32-mcu-discovery-kits/stm32vldiscovery.html

author: Someone
author_rank: Super Contributor
timestamp: September 15, 2016, 12:16:30 am
content: Quote from: vampi-the-frog on September 14, 2016, 07:03:31 amThen how will your handle the data from there? As soon as you want to hear that sound coming in at your arbitrary sample rate you'll need to either provide an audio output at the same sample rate or filter it to the new sample rate (asynchronous sample rate convertor). Audio interfaces don't offer completely free sample rate options, few even provide adjustable sample rates (beyond a few fixed standard rates such as 8/16/32/44.1/48/96 kHz), fewer again will accept an external word clock.https://en.wikipedia.org/wiki/Word_clockThe computer software wants to operate at a single sample rate, so usually all outside sources are either slaved to the computer or brought in through asynchronous sample rate convertors. A lot of the complexity is hidden in editing where all the processing can be done offline (render caches etc) and played at reduced quality until that catches up. Doing everything in realtime is much harder.Its a complicated and large topic:http://www.soundonsound.com/techniques/does-your-studio-need-digital-master-clockQuote

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: September 15, 2016, 05:02:28 pm
content: Yo, I've ordered the dev boards, I'll let you guys know on my progress.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: September 21, 2016, 04:20:45 pm
content: Aight, here's an update.The dev boards have arrived, it's aSTM32VLDISCOVERYboard, which has an on-board ST-Link, and 3Olimex STM32-H103boards. I managed to wire the on-board programmer from the Discovery board to an Olimex board, and managed to get blinky led working.I generated the code with STM32CubeMX, and selected USB Audio Interface in there, but it seems I have to do some magic in the main loop. I'm now looking for a working example.

author: technix
author_rank: Super Contributor
timestamp: September 21, 2016, 04:28:59 pm
content: You can use USB to MIDI chipsets like CH345 to bridge between USB and MIDI. Then find a good DAW that can make use of it.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: September 21, 2016, 06:25:50 pm
content: Well I managed to use this setup once, but now Keil is saying "No target connected" and it's saying the same thing when I connect it to the onboard STM32 as well, so it looks like it's busted for some reason. I managed to program 2 of the Olimex boards once, to get the blinky led program running, but then it started generating this error. The led is still blinky, but it's not programming or detecting it. I'm using SWD.I'll get back when I fix it, I guess.EDIT: aparently it has something to do with the reset pin, I'm still getting the hang of this.

author: pepelevamp
author_rank: Regular Contributor
timestamp: September 21, 2016, 06:53:11 pm
content: Hi dude. Your project is similar to mine.Ya know there's nothing wrong with having it register as two USB devices. A USB soundcard and a USB MIDI controller. You can run them over the same cable by putting in a little USB hub.I wired up a vintage telephone with a USB soundcard and an arduino inside its housing with a passive USB hub. All cheap electronics, but it works. The arduino even has enough guts to ring the bell on its own. It has one USB cable that goes to my PC. Now I can talk on Skype with it, and I can make it ring at will & tell when its off-hook etc.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: September 21, 2016, 08:26:33 pm
content: Quote from: pepelevamp on September 21, 2016, 06:53:11 pmIt ain't easy bein' cheesy!

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: September 28, 2016, 04:51:40 pm
content: Alright, I managed to probe the DAC with a scope, I am seeing a 5MHz clock, which is 1/4 of the 20MHz clock that goes into the sound generator chip. The L/R signal (pin 13 of the uPD6376GS) seems to be about 65KHz, I'll assume it's a power of two, so 65536 Hz. I can't measure too precisely, it's an analog scope. However, the 5MHz clock seems to come in bursts of 48 cycles spaced apart just as the 65KHz L/R signal, so I assume that means it's loading up the value into the DAC at a faster speed than the actual sampling rate, which is ok, since the DAC probably holds the value until a new one is loaded. I have doubts that the sampling rate is 65536 Hz, so it's probably half of that, 32768Hz. I don't know how it divides the 20MHz to 65536Hz, the furthest I can simplify it is 78125/128. Either that or it's actually 64000 Hz, which simplifies to 625/2, or 32000 which simplifies to a division by 625.I'll do some more probing with a logic probe, when it arrives.

author: Buriedcode
author_rank: Super Contributor
timestamp: September 28, 2016, 11:05:00 pm
content: Heres the datasheet for the DAC.http://pdf.datasheetcatalog.com/datasheet/nec/UPD6376GS.pdfI doubt its a '65536Hz' sample rate, you're thinking multiples of 2, not divisions of the clockWith that said, it doesn't have to be a simple division of the clock because as you rightly pointed out, the 'bit clock' and 'LR clock' don't have to have to be related by a simple division factor (but they should come from the same source), as long as the sample bits are clocked in before the next LRCK edge, it stores that in its shift register. This is handy and I've used it to made fairly high quality sound generators from an 8-bit micro, sending out samples over SPI in fast bursts, and manually bit-banging the LRCLK. Either way I suspect its a non standard sample rate, as it looks rather old and was only ever meant to just output analogue - no need to stick to a standard 44.1/32/48 to interface with S/PDIF equipment.I still say you would be better off resampling using a USB soundcard with the audio out tied to the soundcards line-in. Whilst its nice and neat, and possibly more interesting to sniff the bus and collect bytes, getting those to your PC via USB that the PC will recognize as 'audio' will most likely require digital sample rate conversion which opens up a whole can of worms.

author: firehopper
author_rank: Frequent Contributor
timestamp: September 28, 2016, 11:26:07 pm
content: why not use a new teensy 3.6? it can run at up to 240 mhz, plus has 2 dac channels, and can act as usb hosts for what ever you program.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: September 29, 2016, 09:59:22 am
content: Just a few quick notes:- wow, the forum looks really good on mobile, really readable and usable!- it seems 32000 is a standard sample rate, from what some have said, and it also seems really close to my measured rate, so hopefully that'll be the case once I manage to get some more precise measurements, and it might simplify things.- so far I've managed to get one of the STM32 dev boards to act like a HID mouse, it's a lot harder than Arduino programming, lots of libraries and drivers and middlewares and code generators and IDEs and programmer devices and all that, so it'll take a while to wrap my head around it.- I had expected the code generated from STM32Cube to be immediately functional as a dummy USB device, but that is not the case, and the examples one finds are using different versions of libraries and there is a lot of code noise that I'm still wading through.

author: Buriedcode
author_rank: Super Contributor
timestamp: September 29, 2016, 10:18:00 am
content: Depends on what you mean by 'dummy device'. You can't simply import a generic USB library and decide whatever device it should be (HID, mass storage, audio class etc..) because they all operate differently. And yes, even though there are many libraries to help, implementing any USB device is not trivial, if you can find a USB audio class library for the STM32, then of course that would be the way to go - modifying it as you need.If the sample rate is 32kHz you may be in luck, as this is often supported by software, and certainly by the USB audio spec. But unless there's a 8.192/16.384MHz xtal in there, it is more likely to be 31.25kHz as this is can easily be derived from a 4,8 or 16MHz clock - and its also the baud for the MIDI.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: October 01, 2016, 11:28:13 pm
content: 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 thisAlesis io2 Expresscard 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.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: October 05, 2016, 05:01:25 pm
content: 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

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: October 05, 2016, 05:42:27 pm
content: 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.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: October 07, 2016, 11:12:29 pm
content: 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.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: October 12, 2016, 10:03:02 pm
content: 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:#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 __ALIGN_END = {// CONFIGURATION DESCRIPTOR9, // bLength0x02, // bDescriptorType (CONFIGURATION)FIELD_UINT16(255), // wTotalLength4, // bNumInterfaces1, // bConfigurationValue0, // iConfiguration0x80, // 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 wakeup250, // bMaxPower (500mA)// INTERFACE DESCRIPTOR (0.0): class Audio9, // bLength0x04, // bDescriptorType (INTERFACE)0, // bInterfaceNumber0, // bAlternateSetting0, // bNumEndpoints0x01, // bInterfaceClass: Audio0x01, // bInterfaceSubClass0x00, // bInterfaceProtocol0, // iInterface// Class-specific Audio Control Interface Descriptor: Header Descriptor11, // bLength0x24, // bDescriptorType (audio class interface)0x01, // Subtype: Header DescriptorFIELD_BCD(1, 00), // Version: 1,00FIELD_UINT16(53), // Total length3, // Total number of interfaces1, // Interface number2, // Interface number3, // Interface number// Class-specific Audio Control Interface Descriptor: Input terminal descriptor12, // bLength0x24, // bDescriptorType (audio class interface)0x02, // Subtype: Input terminal descriptor1, // bTerminalIDFIELD_UINT16(0x101),// wTerminalType USB Streaming0, // bAssocTerminal2, // bNrChannelsFIELD_UINT16(3), // wChannelConfig// Left Front (L)// Right Front (R)0, // iChannelNames0, // iTerminal// Class-specific Audio Control Interface Descriptor: Output terminal descriptor9, // bLength0x24, // bDescriptorType (audio class interface)0x03, // Subtype: Output terminal descriptor2, // bTerminalIDFIELD_UINT16(0x301),// wTerminalType Speaker0, // bAssocTerminal1, // bSourceID0, // iTerminal// Class-specific Audio Control Interface Descriptor: Input terminal descriptor12, // bLength0x24, // bDescriptorType (audio class interface)0x02, // Subtype: Input terminal descriptor3, // bTerminalIDFIELD_UINT16(0x201),// wTerminalType Microphone0, // bAssocTerminal2, // bNrChannelsFIELD_UINT16(0x0003),// wChannelConfig//Left Front (L)//Right Front (R)0, // iChannelNames0, // iTerminal// Class-specific Audio Control Interface Descriptor: Output terminal descriptor9, // bLength0x24, // bDescriptorType (audio class interface)0x03, // Subtype: Output terminal descriptor4, // bTerminalIDFIELD_UINT16(0x101),// wTerminalType USB Streaming0, // bAssocTerminal3, // bSourceID0, // iTerminal// INTERFACE DESCRIPTOR (1.0): class Audio9, // bLength0x04, // bDescriptorType (INTERFACE)1, // bInterfaceNumber0, // bAlternateSetting0, // bNumEndpoints0x01, // bInterfaceClass: Audio0x02, // bInterfaceSubClass0x00, // bInterfaceProtocol0, // iInterface// INTERFACE DESCRIPTOR (1.1): class Audio9, // bLength0x04, // bDescriptorType (INTERFACE)1, // bInterfaceNumber1, // bAlternateSetting1, // bNumEndpoints0x01, // bInterfaceClass: Audio0x02, // bInterfaceSubClass0x00, // bInterfaceProtocol0, // iInterface// Class-specific Audio Streaming Interface Descriptor: General AS Descriptor7, // bLength0x24, // bDescriptorType (audio class interface)0x01, // Subtype: General AS Descriptor1, // Terminal ID0, // Interface delay in framesFIELD_UINT16(1), // Format// Class-specific Audio Streaming Interface Descriptor: Format type descriptor14, // bLength0x24, // bDescriptorType (audio class interface)0x02, // Subtype: Format type descriptor1, // bFormatType (FORMAT_TYPE_I)2, // bNrChannels3, // bSubframeSize24, // bBitResolution2, // bSamFreqType DiscreteAUDIO_SAMPLE_FREQ(44100),AUDIO_SAMPLE_FREQ(48000),// ENDPOINT DESCRIPTOR9, // bLength0x05, // 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, // bInterval0,0,// Class-specific Audio Streaming Endpoint Descriptor7, // bLength0x25, // bDescriptorType (audio class endpoint)0x01, // Subtype0x01, // bmAttributes//Sampling Frequency0, // bLockDelayUnits UndefinedFIELD_UINT16(0), // wLockDelay Undefined// INTERFACE DESCRIPTOR (2.0): class Audio9, // bLength0x04, // bDescriptorType (INTERFACE)2, // bInterfaceNumber0, // bAlternateSetting0, // bNumEndpoints0x01, // bInterfaceClass: Audio0x02, // bInterfaceSubClass0x00, // bInterfaceProtocol0, // iInterface// INTERFACE DESCRIPTOR (2.1): class Audio9, // bLength0x04, // bDescriptorType (INTERFACE)2, // bInterfaceNumber1, // bAlternateSetting1, // bNumEndpoints0x01, // bInterfaceClass: Audio0x02, // bInterfaceSubClass0x00, // bInterfaceProtocol0, // iInterface// Class-specific Audio Streaming Interface Descriptor: General AS Descriptor7, // bLength0x24, // bDescriptorType (audio class interface)0x01, // Subtype: General AS Descriptor4, // Terminal ID0, // Interface delay in framesFIELD_UINT16(1), // Format// Class-specific Audio Streaming Interface Descriptor: Format type descriptor14, // bLength0x24, // bDescriptorType (audio class interface)0x02, // Subtype: Format type descriptor1, // bFormatType (FORMAT_TYPE_I)2, // bNrChannels3, // bSubframeSize24, // bBitResolution0, // bSamFreqType ContinuousAUDIO_SAMPLE_FREQ(44100), // tLowerSamFreqAUDIO_SAMPLE_FREQ(48000), // tUpperSamFreq// ENDPOINT DESCRIPTOR9, // bLength0x05, // 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, // bInterval0, // bRefresh0, // bSynchAddress// AudioControl Endpoint Descriptor7, // bLength0x25, // bDescriptorType (audio class endpoint)0x01, // Subtype0x00, // bmAttributes0, // bLockDelayUnits UndefinedFIELD_UINT16(0), // wLockDelay Undefined// INTERFACE DESCRIPTOR (3.0): class Audio9, // bLength0x04, // bDescriptorType (INTERFACE)3, // bInterfaceNumber0, // bAlternateSetting2, // bNumEndpoints0x01, // bInterfaceClass: Audio0x03, // bInterfaceSubClass0x00, // bInterfaceProtocol0, // iInterface// MIDIStreaming Interface Descriptor7, // bLength0x24, // bDescriptorType (unknown)1, // bDescriptorSubtype (HEADER)FIELD_BCD(1, 00), // bcdADC .00FIELD_UINT16(65), // wTotalLength// MIDIStreaming Interface Descriptor6, // bLength0x24, // bDescriptorType (unknown)2, // bDescriptorSubtype (MIDI_IN_JACK)1, // bJackType Embedded1, // bJackID0, // iJack// MIDIStreaming Interface Descriptor6, // bLength0x24, // bDescriptorType (unknown)2, // bDescriptorSubtype (MIDI_IN_JACK)2, // bJackType External2, // bJackID0, // iJack// MIDIStreaming Interface Descriptor9, // bLength0x24, // bDescriptorType (unknown)3, // bDescriptorSubtype (MIDI_OUT_JACK)1, // bJackType Embedded3, // bJackID1, // bNrInputPins2, // baSourceID( 0) 21, // BaSourcePin( 0) 10, // iJack// MIDIStreaming Interface Descriptor9, // bLength0x24, // bDescriptorType (unknown)3, // bDescriptorSubtype (MIDI_OUT_JACK)2, // bJackType External4, // bJackID1, // bNrInputPins1, // baSourceID( 0) 11, // BaSourcePin( 0) 10, // iJack// ENDPOINT DESCRIPTOR9, // bLength0x05, // bDescriptorType (ENDPOINT)0x03, // bEndpointAddress OUT Endpoint:3// 0... .... = Direction: OUT Endpoint (0x02)// .... 0011 = Endpoint Number (0x03)0x02, // bmAttributes// .... ..10 = Transfertype: Bulk-TransferFIELD_UINT16(16), // wMaxPacketSize// .... ..00 0001 0000 = Maximum Packet Size (16)0, // bInterval0, // bRefresh0, // bSynchAddress// MIDIStreaming Endpoint Descriptor5, // bLength0x25, // bDescriptorType (unknown)1, // bDescriptorSubtype (GENERAL)1, // bNumEmbMIDIJack1, // baAssocJackID( 0) 1// ENDPOINT DESCRIPTOR9, // bLength0x05, // bDescriptorType (ENDPOINT)0x84, // bEndpointAddress IN Endpoint:4// 1... .... = Direction: IN Endpoint (0x02)// .... 0100 = Endpoint Number: 0x040x02, // bmAttributes// .... ..10 = Transfertype: Bulk-Transfer (0x02)FIELD_UINT16(16), // wMaxPacketSize// .... ..00 0001 0000 = Maximum Packet Size0, // bInterval0, // bRefresh0, // bSynchAddress// MIDIStreaming Endpoint Descriptor5, // bLength0x25, // bDescriptorType (unknown)1, // bDescriptorSubtype (GENERAL)1, // bNumEmbMIDIJack3 // baAssocJackID(0)};

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: October 16, 2016, 09:00:28 pm
content: I have switched over tolibopencm3and I've already gotten USB MIDI to work. Now to add the USB Audio Streaming stuff in there.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: October 22, 2016, 11:11:57 am
content: 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 withCode:arecord -D hw:1,0,0 -c 2 -f S16_LE -r 96000 -d 1 foo.wavThe wav file looks like a series of consecutive incrementing values:Code: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: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;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 datasending_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: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:#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;} __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 theCone has I2S.

author: Cervisia
author_rank: Regular Contributor
timestamp: October 22, 2016, 01:35:34 pm
content: QuoteI²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.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: October 22, 2016, 09:31:53 pm
content: Quote from: Cervisia on October 22, 2016, 01:35:34 pmIn my case it seems it's two clocks somehow.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: October 26, 2016, 09:03:35 am
content: 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.

author: vampi-the-frog
author_rank: Regular Contributor
timestamp: December 13, 2016, 07:49:49 pm
content: 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.