Image (6).jpg

This is my first SAMA5D4 firmware that takes a reasonable sample of audio range signals.

I'm using the ADC buffer mechanism. The converter fills the buffer in the background.

I'm reading the values and log them. Later I'll use them to drive the light organ of the enchanted table.

 

Photo 25-05-15 21 18 40.jpg

 

 

What's Happening in the Firmware?

 

I'm doing exactly the same as what's documented on IioAdcDriver < Linux4SAM < TWiki.

But in C++. You can find the instructions back in the code.

For clarity, I'm using the same comments as on the AT91 pages.

 

Set up the channels in use

linux

echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_en



c++

      ofstream osChannel("/sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_en", ios::out);
      if (osChannel.is_open()) {
        osChannel << "1";
        osChannel.close();
      } else {
        cout << "Unable to open file " << "/sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_en" << "\n";
      }



Set up the trigger we want to us

linux

echo "fc034000.adc-dev0-continuous" > /sys/bus/iio/devices/iio:device0/trigger/current_trigger



c++

      ofstream osTrigger("/sys/bus/iio/devices/iio:device0/trigger/current_trigger", ios::out);
      if (osTrigger.is_open()) {
        osTrigger << "fc034000.adc-dev0-continuous";
        osTrigger.close();
      } else {
        cout << "Unable to open file " << "/sys/bus/iio/devices/iio:device0/trigger/current_trigger" << "\n";
      }


 

Set up the buffer length

linux

echo 100 > /sys/bus/iio/devices/iio:device0/buffer/length



c++

      ofstream osLength("/sys/bus/iio/devices/iio:device0/buffer/length", ios::out);
      if (osLength.is_open()) {
        osLength << MUESTRAS;
        osLength.close();
      } else {
        cout << "Unable to open file " << "/sys/bus/iio/devices/iio:device0/buffer/length" << "\n";
      }



Enable the capture

linux

echo 1 > /sys/bus/iio/devices/iio:device0/buffer/enable



c++
      ofstream osEnable("/sys/bus/iio/devices/iio:device0/buffer/enable", ios::out);
      if (osEnable.is_open()) {
        osEnable << "1";
        osEnable.close();
      } else {
        cout << "Unable to open file " << "/sys/bus/iio/devices/iio:device0/buffer/enable" << "\n";
      }



 

 

After that point, the ADC starts filling the buffer - available as character device  /dev/iio:device0.

I then go on and read these 128 samples of the buffer. After that, my code will go to do the light organ work - a topic for the next post.

 

There's still some dodgy code in my program. My algorithm to read from that character device isn't good.

I do know how to do it properly (I have the c example code from generic_buffer.c available).

I was just hoping that I could simplify that code using a c++ character stream. I just don't seem to be able to use the stream mechanism reliable with a volatile character device yet.

I sometimes receive the two bytes that form my value in reverse order. I know that's me, because the sample code does it just fine. So there's still work to do.

 

 

  while(1) {
    ifstream myfile(fileName, ios_base::binary);
    if (myfile.is_open()) {




      for( i=0; i < MUESTRAS; i++) {




        myfile >> uSampleA;
        myfile >> uSampleB;


        /**
         * Obviously, I don't know what I'm doing here.
         * I need to study generic_buffer.c to really understand
         * how to interpret /dev/iio:device0
         * I have a 10 bits result, most likely stored in 2 bytes
         * But the way I'm reading it back seems to give a random
         * order of the high and low bytes
         *
         * I'd better start learning the way to properly read the buffer
         * but for my light organ, the errors are in the noise range
         */


        uShiftedSample = uSampleA << 8;
        uShiftedSample |= uSampleB;


        if (uShiftedSample > 1023U) {
          uShiftedSample = uSampleB << 8;
          uShiftedSample |= uSampleA;
        }


        //cout << uSampleA << " " << uSampleB << " " << uShiftedSample << "\n";


//        data[i] = uShiftedSample/4-128; //Convertimos de 0..1024 a -128..127
        data[i] = uShiftedSample; //Convertimos de 0..1024 a -128..127
        im[i] = 0;                    // parte imaginaria = 0


      }


      cout << "\nsamples :\n";
      for( i=0; i < MUESTRAS; i++) {
        cout << (int)data[i] << ",";
      }
      cout << "\n";




    } else {
      cout << "Unable to open file " << fileName << "\n";
    }


    // taken out of sample loop
    myfile.close();
  }



 

For my light organ however, this sample quality will do.

In the next installment I'll transpose the samples to the -128..127 range.

Then to go through the FFT library, and I'll chop them up in bass, middle and treble...

 

Table of Contents
Chapter 1: Fix the turntable
1: Perpetuum Ebner Musical 1
2: A Time to Kill and a Time to Heal
3: Preparation for Motor Drive
4: Motor control with Infineon Motor Shield and Arduino UNO
5: Turntable speed sample testbed with Arduino UNO
6: Turntable Speed Sensor design
7: Control Theory - End of Chapter 1
Chapter 2: First Enchantments
8: Digital Light Organ Enchantment
9: Autonomous Servo Lift
10: SMD Time - Solder the IR Speed Sensor PCB
11: Yelp - who can Help me to Compile and Run my First SAMA5D4 C Program
12: Son et Lumiere - End of Chapter 2
Chapter 3: Taming the Board
13: Breakthrough - Run my own C++ Program on the SAMA5D4
14: Digital Light Organ Input Buffer
15: SAMA5D4 Blinky
16: Scope Creep
17: Audio Sampling with 16-bit ADC ADS8343
18: Sending Files to SAMA5D4 over USB
19: Port my Light Organ from Arduino to SAMA5D4
20: Fast Fourier Transform on the SAMA5D4 - End of Chapter 3
Epilogue: Reaching for the Clouds
21: Right-Sizing my Plans
22: My Own C++ Buffered Sampler on the SAMA5D4
Interlude
23: Building In the Motorized Light Organ
24: Up to the Clouds with Yún
25: Publish or Perish
26: Turntable Finished
Stretch & Boni
Bonus 1a: Remote Light Organ with WiFI pt. 1
Bonus 1b: Remote Light Organ with WiFI pt. 2
Grande Finale: Paho MQTT Client on the SAMA5D4
Related blog
Vintage Turntable repair: Can I fix a Perpetuum Ebner from 1958
Review 1: Atmel SMART SAMA5D4 Xplained Ultra Unboxing and First Steps
Review 2: Atmel SMART SAMA5D4 Xplained Ultra - Building the Libraries from Source
Review 3: Digital Continuous Rotation (360°) Servo Part 1
Review 4: Digital Continuous Rotation (360°) Servo Part 2
Review 5: Atmel SMART SAMA5D4 Xplained Ultra - TCP/IP running
Review 6: Atmel SMART SAMA5D4 Xplained Ultra - LINUX Distro with SSH support
poem
Enchanted Objects: Let's work together to tame the ATMEL SMART SAMA5D4 Xplained Ultra kit
17 bis: Off South...
Review 7: Atmel SMART SAMA5D4 Xplained Ultra - C++ ADC Example on Linux
Review 8: Atmel SMART SAMA5D4 Xplained Ultra - Product Review
Review 9a: Atmel SMART SAMA5D4 Xplained Ultra - Set up ADC Buffer with Hardware Trigger Part 1
Review 9b: Atmel SMART SAMA5D4 Xplained Ultra - Set up ADC Buffer with Hardware Trigger Part 2
Review 10: Atmel SMART SAMA5D4 Xplained Ultra - New Content on AT91.com
1958 Turntable from the Black Forest - Summary of the Enchanted Player Story