1

I am a newbie with DACs, but basically, I have a FPGA (DE1-SOC) running Linux. Hooked up to it is a LTC2607 DAC. Everything is operating smoothly as far as Linux recognizing the DAC over I2C and everything.

My question is regarding how to generate a sinusoidal waveform using the cordic algorithm. I have an algorithm that outputs an array of 16 hex values.

{0x00003243, 0x00001DAC, 0x00000FAD, 0x000007F5, etc...}

The code that runs the I2c/DAC accepts a 16-bit "DAC Code", which then is converted to an analog output:

uint16_t LTC2607_code(float dac_voltage, float LTC2607_lsb, float LTC2607_offset)
{
  uint16_t dac_code;
  float float_code;
  float_code = (dac_voltage - LTC2607_offset) / LTC2607_lsb;                                      // Calculate the DAC code
  float_code = (float_code > (floor(float_code) + 0.5)) ? ceil(float_code) : floor(float_code);   // Round
  if (float_code >= 65535.0)                                                                      // Limits the DAC code to 16 bits
    float_code = 65535.0;
  dac_code = (uint16_t) (float_code);                                                             // Convert to unsigned integer
  return (dac_code);
}

I know for direct digital synthesis you have to "interpolate" the points (voltage levels) along the sinusoid. My thinking is that I would send those value across the I2C, one-by-one, and however fast those 16 hex values are passed across the I2C (set by the Master (FPGA) clock @ ~10MHz) is what frequency the sin wave will be?

The code for writing to the DAC is as follows:

int8_t LTC2607_write(uint8_t i2c_address, uint8_t dac_command, uint8_t dac_address, uint16_t dac_code)
{
    int fd;
    int ret;
    char *device;
    uint8_t command_byte;
    uint8_t buffer[3];

    command_byte = dac_command | dac_address; // Build the DAC command byte

    // Open the I2C device
    device = LTC2607_get_device_name();
    fd = open(device, O_RDWR);
    if (fd < 0)
    {
        return (1);
    }

    // Select the desired address
    ret = ioctl(fd, I2C_SLAVE, i2c_address);
    if (ret < 0)
    {
        close(fd);
        return (1);
    }

    // Build the I2C command
    buffer[0] = command_byte;
    buffer[1] = (dac_code >> 8) & 0xFF;
    buffer[2] = dac_code & 0xFF;

   // Write the command to the I2C bus
   ret = write(fd, buffer, 3);
   if (ret < 3)
   {
     close(fd);
     return (1);
   }

   // Close the device
   close(fd);

   return (0);
 }

How would I convert that string of 16 hex values into a sinusoid using the above LTC2607_write function?

  • Could you please explain a bite more detailles, what your actual problem is and how the bits of your question fit together? And please take care to indent any code you show. A wall of text is not attracting any readers. – Gerhardh Sep 10 '18 at 05:57
  • How is the code you show related to your question? Your seem to ask about generating (quality and frequency) the values for the sine wave. Converting analog to digital doesn't seem to be related. Also cording algorithm is not related to the conversion. – Gerhardh Sep 10 '18 at 05:58
  • If you already have 16 values representing your wave, for which purpose do you want to generate values using Cordic algo? – Gerhardh Sep 10 '18 at 06:01
  • I added more detail to my question above. Let me know if that clarifies my question. – Daniel Pavlovsky Sep 10 '18 at 06:27
  • Max SCL frequency for LTC2607 is 400kHz. How many points per sine cycle do you want to have? What frequency do you want to generate? One Write&Update operation takes `(8+1*3)=11` bits, so for 400kbits/s you can transfer up to `400000/11 =~ 36000` points per second (continous i2c transfer without any stops, anytime, with a device address transferred only once at the beginning). Now the question is, what frequency do you want to generate? – KamilCuk Sep 10 '18 at 06:56
  • 1
    A real transfer value would rather be for a single Write&Update operation with device address, that's `STARTtime + (8+1)*4 bits + STOPtime + MIN_BUS_FREEtime =0.6us + 36bits+0.6us+1.3us = 36bits / 4000000bits/s + 2.5us = 90us+2.5us =~ 100us -> 10kHz`. So I estimate, you can should get safe 10000 unique points per second using this DAC and ideal conditions. As to you code, don't open&close the file each time you do transfer (slows down), keep the file opened all the time with slave address selected, call only write or better `i2c_smbus_access` family function to transfer bytes via i2c. – KamilCuk Sep 10 '18 at 06:57
  • Thanks for the reply Kamil. The frequency range I would be aiming for is between 10 and 20KHz. Ideally 15KHz. I understand about not closing the file, but still a little confused as to how to pass those 16 hex values into the write function, and how to scale the frequency so it would be around 10-15KHz...? – Daniel Pavlovsky Sep 10 '18 at 17:21

0 Answers0