Serial comm with Maple

Re: Serial comm with Maple

Postby clee » Sat Jul 07, 2012 7:31 am

The approach of communicating via a FTDI breakout to the maple while using the audio codec shield appears to work, at least with a simple example.

I added code to the sine generator example to write to "Serial3" at up to 1500000 baud this morning. The tone still sounds glitch free.

Here's the code with a little explaination of the connections.

Code: Select all
/*
sine_generator_plus_serial3.pde (MAPLE)

Based upon sine_generator in the Open Music Labs AudioCodec_Maple examples, the code adds only writing to USART Serial3 while audio_codec is running too. It just outputs a count of the main loop iterations every N steps while an interupt generates the sine tone outupt. -Chris Lee-Messer

guest openmusiclabs 7.13.11
this program creates a sinewave of variable frequency and
amplitude, presented at both left and right outputs. there
isnt any interpolation, so you only get 256 discrete frequencies
across the span of 44Hz to 10kHz.


Hardware connections
--------------------
From the the maple documentaiton the USART Pin Map
         Tx     Rx      Ck      cts     rts
Serial3   D29   D30   D31   D32   D33
(this also applies to the Maple RET6 edition)
These pins are also listed as being ***5V tolerant***


I chose Serial3 because these pins are on the 2x8 header "EXT" block which aren't
connected to the audio codec shield.


So I connected 3 wires to my FTDI basic board:
   D29 (Tx) to the Rx on the FTDI basic board
   D30 (Rx) to the Tx on the FTDI basic board
        GND to GND on on the FTDI basic board

License: what every Open Music Labs published the Audiocodec files under

   
*/

// setup codec parameters
// must be done before #includes
// see readme file in libraries folder for explanations
#define SAMPLE_RATE 44 // 44.1kHz sample rate
#define ADCS 2 // use both ADCs

// try faster 9600, 19200, 14400, 38400, 57600, 56000,
// 115200, 128000, 230400,460800, 153600, 256000,921600
// the FTDI 232R datasheet says it can go to 3 Mbaud
#define BAUDRATE 1500000

#define N_SENDSERIAL 100 // send a serial value every N steps through the loop   
// include necessary libraries
// note the Maple library
#include <AudioCodec_Maple.h>

// create data variables for audio transfer
// even though there is no input needed, the codec requires stereo data
// note the uint16 typedef, there is no "unsigned int16" type
int16 left_in = 0; // in from codec (LINE_IN)
int16 right_in = 0;
int16 left_out = 0; // out to codec (HP_OUT)
int16 right_out = 0;

// create variables for ADC results
// it only has positive values -> unsigned
uint16 mod0_value = 0;
uint16 mod1_value = 0;

// create sinewave lookup table
// note the int16, ints are 32b in Maple land
int16 sinewave[] __FLASH__ = {
  // this file is stored in AudioCodec_Maple.h and is a 1024 value
  // sinewave lookup table of signed 16bit integers
  // you can replace it with your own waveform if you like
  #include <sinetable.inc>
};
uint16 location; // lookup table value location
unsigned int g_count = 0;

void setup() {
  Serial3.begin(BAUDRATE);
  SerialUSB.end(); // usb conflicts with the codec in this mode
                   // a different operating mode which allows both
                   // is in the works
  // setup codec and microcontroller registers
  AudioCodec_init(); // call this last if you are setting up other things
}

void loop() {
  // while (1); // reduces clock jitter

  if (!(g_count % N_SENDSERIAL)) {
     Serial3.println(g_count);
  }
  g_count++;
}

// timer1 interrupt routine - all data processed here
void AudioCodec_interrupt() {

  // &'s are necessary on data_in variables
  AudioCodec_data(&left_in, &right_in, left_out, right_out);
 
  // create some temporary variables
  // these tend to work faster than using the main data variables
  // as they arent fetched and stored all the time
  int16 temp1;
 
  // create a variable frequency and amplitude sinewave
  // fetch a sample from the lookup table
  temp1 = sinewave[location];
  // step through table at rate determined by mod1
  // use upper byte of mod1 value to set the rate
  // and have an offset of 1 so there is always an increment.
  location += 1 + (mod1_value >> 8);
  // if weve gone over the table boundary -> loop back
  // around to the other side.
  location &= 0x03ff; // fast way of doing rollover for 2^n numbers
                      // otherwise it would look like this:
                      // if (location >= 1024) {
                      // location -= 1024;
                      // }
 
  // set amplitude with mod0
  // multiply our sinewave by the mod0 value
  // since it returns a 32bit value it needs to be scaled with ">> 16"
  temp1 = (temp1 * mod0_value) >> 16;
  left_out = temp1; // put sinusoid out on left channel
  right_out = -temp1; // put inverted version out on right chanel

  // get ADC values
  // & is required before adc variables
  AudioCodec_ADC(&mod0_value, &mod1_value);


  // you dont need to reti() with Maple
}




clee
 
Posts: 7
Joined: Thu Jul 05, 2012 10:18 pm

Re: Serial comm with Maple

Postby guest » Sat Jul 07, 2012 1:23 pm

thats awesome
glad to hear its working
a number of people have asked how to get the codec data into the computer
and this looks like a pretty good way
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: Serial comm with Maple

Postby clee » Mon Jul 09, 2012 5:44 pm

Yes, the serial ports seems like a pretty good option.

I have done a few tests and with a baud setting of 2000000, a simple python test client can transfer ra 1024 16-bit ints is about 13.5ms while the maple+audio codec shield continues to play the sine wave tone. That's about 151 kB/s including the overhead for my not-very-efficient python code as compared to the theoretical, no-overhead-max of 250 kB/s.

At the next speed above that, 30000000, the connection can't be made, which makes sense given that 2.25 Mb/s is the spec sheet limit on some of the maple's USARTs.

I'm pretty sure things could be faster. I would think options include looking at using dma or use of the other SPI interface (18 Mb/s) might be the way to go.

I put my test doodles in a repo if people would like to look (the sketch is called "upload_play"):
https://bitbucket.org/cleemesser/maple-stm32-learn/src/428f89184565/upload_play
clee
 
Posts: 7
Joined: Thu Jul 05, 2012 10:18 pm

Re: Serial comm with Maple

Postby guest » Fri Jul 27, 2012 4:38 pm

so i did some more digging into the usb problem

the initial problem had to do with the fact
that the maple usb interrupt can not be blocked for more than a few microseconds
which the audiocdec library clearly does quite frequently

so i rewrote the audiocodec library to only take a fraction of a microsecond in the interrupt
and this allowed the maple usb to function again
but now the maple usb interrupt is blocking the audiocodec interrupt
and the data is not getting clocked out to the codec at regular enough intervals
this gives audible clicks in the playback data

im going to look at a few things on a scope
but i think this is the best the maple can do for usb
until the maple usb library is rewritten
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: Serial comm with Maple

Postby diydsp » Fri Jul 27, 2012 5:52 pm

clee wrote:Yes, the serial ports seems like a pretty good option.

I have done a few tests and with a baud setting of 2000000, a simple python test client can transfer ra 1024 16-bit ints is about 13.5ms
...
I put my test doodles in a repo if people would like to look (the sketch is called "upload_play"):
https://bitbucket.org/cleemesser/maple-stm32-learn/src/428f89184565/upload_play


dude, that is awesome work.

BTW, I might be attaching to that serial port for other purposes, such as modifying the timeout in the bootloader. Have you got any references for how to attach, e.g. an FTDI 3V serial port to the Maple?
http://diydsp.com is where I teach people Do-It-Yourself Digital Signal Processing for music instruments and other applications.
diydsp
 
Posts: 21
Joined: Mon Dec 19, 2011 10:44 pm

Re: Serial comm with Maple

Postby clee » Fri Jul 27, 2012 9:24 pm

I don't have too much experience with this sort of thing. What I have done after I to look up the correct pins numbers in the documentation http://leaflabs.com/docs/hardware/maple.html#gpio-information, is to run short jumper cables like so:

For a basic two-way communication setup there are 3 wires to hook up :

Code: Select all
maple ----- ftdi
Tx ----- Rx
Rx ----- Tx
Gnd ----- Gnd


As far as I can tell, for reliable transmission at higher speeds it may be necessary to use flow control. For to support this in hardware this requires addional connections:
Code: Select all
maple      ftdi
Tx ----- Rx
Rx ----- Tx
Gnd ----- Gnd
RTS ----- CTS
CTS ----- RTS


I'm currently working out the code to do the flow control. There is an example in the ST peripheral library examples. I haven't found RTS/CTS flow control in libmaple yet and I'm not sure how much is handled by the USART itself in hardware and how much one needs to modify one's code to use RTS/CTS.
clee
 
Posts: 7
Joined: Thu Jul 05, 2012 10:18 pm

Re: Serial comm with Maple

Postby guest » Mon Jul 30, 2012 6:08 pm

im getting closer to having the usb working
with the help of the leaflabs folks
i found a way to have nested interrupts
placing this in setup gives timer4 priority

Code: Select all
  SCB_BASE->AIRCR = 0x05FA0300;
  nvic_irq_set_priority(NVIC_TIMER4, 0);
  nvic_irq_set_priority(NVIC_USB_HP_CAN_TX, 15);
  nvic_irq_set_priority(NVIC_USB_LP_CAN_RX0, 15);
  nvic_irq_set_priority(NVIC_USBWAKEUP, 15);


i then created a buffer for the data
and it greatly reduces the clicks
but they are not all gone yet

ultimately i think the uart trick is way easier
and a lot less computationally intensive
the usb handler wastes a lot of time

the main reason i want to get usb working
is so i dont have to hit reset every time i load code
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: Serial comm with Maple

Postby guest » Mon Jul 30, 2012 6:38 pm

ok this seems to work

Code: Select all
/*
sine_generator.pde (MAPLE)
guest openmusiclabs 7.30.12
test program for usb communication with codecshield
plays back a glitch free audio stream while usb is active
*/

// setup codec parameters
// must be done before #includes
// see readme file in libraries folder for explanations
#define SAMPLE_RATE 44 // 44.1kHz sample rate
#define ADCS 2 // use both ADCs

// include necessary libraries
// note the Maple library
#include <AudioCodec_Maple.h>
#include <scb.h> // for setting the interrupt priorities

int16 left_in = 0; // in from codec (LINE_IN)
int16 right_in = 0;
volatile int16 left_out = 0; // out to codec (HP_OUT)
volatile int16 right_out = 0;
volatile int16 waittimer = 0;

uint16 mod0_value = 0;
uint16 mod1_value = 0;

int16 buffer[8];
volatile uint8 buffertop = 0;
volatile uint8 bufferofset = 2;

int16 sinewave[] __FLASH__ = {
  #include <sinetable.inc>
};
uint16 location; // lookup table value location


void setup() {
  // setup codec and microcontroller registers
  AudioCodec_init(); // call this last if you are setting up other things
  SCB_BASE->AIRCR = 0x05FA0300;
  nvic_irq_set_priority(NVIC_TIMER4, 0);
  nvic_irq_set_priority(NVIC_USB_HP_CAN_TX, 15);
  nvic_irq_set_priority(NVIC_USB_LP_CAN_RX0, 15);
  nvic_irq_set_priority(NVIC_USBWAKEUP, 15);
}

void loop() {
  while (1) { // reduces clock jitter
  while (waittimer == 0);
  while (!(SPI1_BASE->SR & (1 << SPI_SR_RXNE_BIT))) { // wait for data to arrive
  }
  left_in = SPI1_BASE->DR; // recieve left data
  while (!(SPI1_BASE->SR & (1 << SPI_SR_RXNE_BIT))) { // wait for data to arrive
  }
  right_in = SPI1_BASE->DR; // recieve right data
  waittimer = 0;
  while (bufferofset < 6) {
    int16 temp1;
    temp1 = sinewave[location];
    location += 1 + (mod1_value >> 8);
    location &= 0x03ff;
    temp1 = ((temp1 * mod0_value) >> 16) & 0xfffe;
    buffer[(buffertop + bufferofset)&0x07] = temp1;
    bufferofset++;
  }
  AudioCodec_ADC(&mod0_value, &mod1_value);
  }
}

// timer1 interrupt routine - all data processed here
void AudioCodec_interrupt() {
  left_out = buffer[buffertop];
  GPIOA_BASE->BSRR = 0x00000010; // set ss high
  SPI1_BASE->DR = left_out; // send out left data
  asm volatile ("nop"); // delay for appropriate timing
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  GPIOA_BASE->BSRR = 0x00100000; // set ss low
  right_out =  left_out;
  buffertop++;
  bufferofset--;
  buffertop &= 0x07;
  while (!(SPI1_BASE->SR & (1 << SPI_SR_TXE_BIT))) { // wait for data to be sent
  }
  SPI1_BASE->DR = right_out; // send out right data
  waittimer = 1;
}


if others use it and it seems reasonable
i will write it up as an alternate library function
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: Serial comm with Maple

Postby clee » Sat Aug 04, 2012 10:52 pm

Thank you for the USB code. I'll give it a try. This also gives helped me learn about how the interrupt priorties are set in the libmaple way of doing things.

I've noticed reliability issues with the using the ft232R based breakout naively. The basic tx/rx connection works pretty well at 2Mb/s but eventually there is a transfer failure. It's unpredictable but usually it makes it about 70-100Mb of transfer and it fails. Because it is rare, I haven't pinned down the exact cause of the problem. I need to figure out if I can read error flags from the ftdi interface. There's probably a system that I need to google for.

One guess about the problem is that the USB bus on my linux laptop is occasional off serving something else occasionally and causing a delay in accepting data in the middle of the transfer from the maple---bits overrun the small buffers in the ft232 occurs and the data stream is corrupted.

I'm trying out using the ft2232H instead which has 4k buffers built in. So far I've repeatedly transferred 2kB at about 180-190 kB/s (using the 2,000,000 baud rate seting) for about 2 hours without an error. :-)

[got it from dangerous prototypes http://dangerousprototypes.com/docs/FT2 ... kout_board]
clee
 
Posts: 7
Joined: Thu Jul 05, 2012 10:18 pm

Re: Serial comm with Maple

Postby clee » Wed Aug 15, 2012 1:15 pm

Update: Things are going well using the USART. Both the FT232RL and the FT2232H based breakouts are working well and consistently giving ~186kB/s with bit rates of 2Mb/s in my test code. My reliability issues initially resolved with using hardware flow control and I've started adding to libmaple to make RTS/CTS flow control available in libmaple. [See http://forums.leaflabs.com/topic.php?id ... post-12454 and https://github.com/cleemesser/libmaple]

However, I think that at least part of my reliability issue was due to a boarderline bad jumper cable, because after a recent cleanup and change of many of the wires, I can't reproduce the error anymore. I really need to get a logic analyzer and my oscilloscope working again.

The next step is to try SPI with its 18Mb/s bandwidth. I've started trying out the olimex maple clone as well, in part, because it has a nice angled UEXT connector which makes USART3 and SPI available even when the audio codec board is mated to the maple.
clee
 
Posts: 7
Joined: Thu Jul 05, 2012 10:18 pm

Previous

Return to Audio Codec Shield

Who is online

Users browsing this forum: No registered users and 1 guest