Go Down

Topic: Arduino Serial.write 16 bit signed PCM Samples (Read 174 times) previous topic - next topic

RiceBaII

Hi Guys,

I am trying to send 16 bit signed PCM Samples via Serial.write.
I am using the following code:
Code: [Select]
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))


bool start=0;
byte buf00[1024];
byte buf01[1024];
unsigned long recByteCount = 0L;
unsigned int bufByteCount = 0;
unsigned int bufByteCount2 = 1;
byte bufWrite = 0;

byte m;
byte j;
int k;

void setup() {
  // put your setup code here, to run once:
  Setup_timer2();
  Setup_ADC();
  Serial.begin(115200);
  while(!Serial);
  //calibration();
  Serial.println("Calibration finished");
   


}

void loop() {
  while(1){
  // put your main code here, to run repeatedly:
  if(start==0){
    sbi (TIMSK2, OCIE2A); // enable timer interrupt, start grabbing audio
    start=1;
  }

  if (recByteCount % 2048 == 1024) { Serial.write(buf00,1024); }
  if (recByteCount % 2048 == 0) { Serial.write(buf01,1024);}
 

  }
}


void Setup_timer2() {

  TCCR2B = _BV(CS21);  // Timer2 Clock Prescaler to : 8
  TCCR2A = _BV(WGM21); // Interupt frequency  = 16MHz / (8 x 90 + 1) = 22191Hz
  OCR2A = 200; // Compare Match register set to 90

}


void Setup_ADC() {

  ADMUX = 0x65; // set ADC to read pin A5, ADLAR to 1 (left adjust)
  cbi(ADCSRA,ADPS2); // set prescaler to 8 / ADC clock = 2MHz
  sbi(ADCSRA,ADPS1);
  sbi(ADCSRA,ADPS0);
}


ISR(TIMER2_COMPA_vect) {

  sbi(ADCSRA, ADSC); // start ADC sample
  while(bit_is_set(ADCSRA, ADSC));  // wait until ADSC bit goes low = new sample ready
    m = ADCL; // fetch adc data
    j = ADCH;   
    k = (j << 8) | m; // form into an int
    k -= 0x0200; // form into a signed int
    k <<= 6; // form into a 16b signed int
     
  recByteCount++;
  bufByteCount=bufByteCount+2;
  bufByteCount2=bufByteCount2+2;
  if (bufByteCount2 == 1025 && bufWrite == 0) {
    bufByteCount = 0;
    bufByteCount2=1;
    bufWrite = 1;
  } else if (bufByteCount2 == 1025 && bufWrite == 1) {
    bufByteCount = 0;
    bufByteCount2=1;
    bufWrite = 0;
  }

  if (bufWrite == 0) { buf00[bufByteCount2] = highByte(k);
                       buf00[bufByteCount] = lowByte(k);}
  if (bufWrite == 1) { buf01[bufByteCount2] = highByte(k);
                       buf01[bufByteCount] = lowByte(k);}
  }




I thought it would be possible to do an analog readout of Pin A5 with my Mega2560 and then turn that value into a 16 bit signed Integer.
Then, send it over Serial.write by sending the lowByte first and then the highByte.

Did i program it wrong or is it even possible to send it like that?
Do you guys have an alternative way to send 16 bit signed Samples over Serial or maybe another method?

Thanks a lot in advance.

Best regards,
Riceball

Grumpy_Mike

I would send the 10 bit sample as two bytes with five bits of sound sample and the top three bits indicating if the five bits are the least or most significant. Then at the receive end you always know which two five bit words to combine.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy