Parallel Transmission from DUE to my DDS Board

Does the parallel transmission of data work in Arduino in the following manner?
The data does not seem to get written since I can't see a change in my DDS module. Any suggestions. I already got a hold of some Serial data transfer code but it did not help me much with parallel transfer.

void setup() {  
  // Set the Mode of the Address and Data pins
// Address pins
  pinMode(23, OUTPUT);
  pinMode(25, OUTPUT);
  pinMode(27, OUTPUT);
  pinMode(29, OUTPUT);
  pinMode(31, OUTPUT);
  pinMode(33, OUTPUT);
  // Data pins
  pinMode(24, UTPUT);
  pinMode(26, OUTPUT);
  pinMode(28, OUTPUT);
  pinMode(30, OUTPUT);
  pinMode(32, OUTPUT);
  pinMode(34, OUTPUT);
  pinMode(36, OUTPUT);
  pinMode(38, OUTPUT);

  // Write Pin
  pinMode(writePulsePin, OUTPUT);
  // Read Pin
  pinMode(readPulsePin, OUTPUT);
  // Reset Pin
  pinMode(resetPin, OUTPUT);
  // Update Pin
  pinMode(updatePin, OUTPUT);
  //COM13 Serial between Arduino Due SAM3X and Serial Monitor.
  Serial.begin(115200);
  //COM9 serial between Due and DDS Control Console.
  Serial1.begin(19200);
  while(!Serial){};
} //end setup


loop{
     setAddressAndData(Address, Data, Length,  Setter) 
{
  if (DEBUG) Serial.println( " Set function = " + Setter); 
  int addLength = Length;
  int dataLength = Length;

  if (DEBUG) {
    Serial.println(" addLength = " + String(addLength));
    Serial.println(" dataLength = " + String(dataLength));
  }
  //   since if there are 6 address bytes there will also be 6 data bytes. The
  //   length of the address will be equal to the the sizeof the Address.
  //   The number of bytes in an address will equal the size of the Address


  // numBytes is same for Data as for Address
  int numBytes = Length / 8;

  //   The code will be setting the pin direction to output. then for each bit
  //   in the address or Data; we will set the pin value to either 0 or 1
  //   depending on the pin position in the Data or Address. I did not use
  //   the DDR's directly for this operation since the pins were located on
  //   different ports which would have made iteration a nightmare and in the
  //   end waste even more memory.
  
  for ( numBytes; numBytes >= 1; numBytes--)
  {
     //  Step 1. Generate the Addresses
     //  The startPin values come from the board Arduiono Due from the parallel
     //  port consisting of bits 20 - 55 of which we use 24 - 38 all even. 23 - 33 all odd
     //  are the address bits, data comes from the even bits.
     
    if (DEBUG) Serial.println(" ==> numBytes = " + String(numBytes));
    int startPin = 23;
    
    //  Main loop for the Address setup

    //  addLength - 3 since we want to start with the 6th bit per byte
    //  hence 48 - 1 to get actual bit position - 2 since that there are
    //  only 6 bits in each address hextuplt. i.e, Instead of starting at
    //  bit 47, 45 is the start point and it ends at 40. 45 to 40 inclusive are
    //  6 bits.

    for ( int bit = addLength - 3; bit >= addLength - 8; bit--) {
      //pinMode(startPin, OUTPUT);
      digitalWrite(startPin, (bitRead(Address, bit)));

      if (DEBUG) {
        Serial.print(" ==> startPin = " + String(startPin) +" ==> bit = " + String(bit));
        int value = bitRead(Address, bit);
        Serial.println(" ==> The read bit value = " + String(value));
      }
      // do next pin
      startPin += 2;
    }

    // Step 2. Generate the Data segments
    // The startPin values come from the board Arduino Due from the parallel
    // port consisting of bits 20 - 55 of which we use 23 - 41. 24 - 38 are the
    // data bits.  37 is the NotWrite pin and 39 is the Read pin. The boards 
    // Read not and Not Write did not align with the DDS pin out that's why it was 
    // generated separately.

    if (DEBUG) Serial.println(" ==> numBytes = " + String(numBytes));

    // Main loop for the Data setup

    // Data - 1 since we want to start with 47th bit hence 48 - 1 to get the
    // actual bit position since there are 8 bits in each Data byte. i.e,
    // Starting at bit 47, it ends at 40. 47 to 40 inclusive are 8 bits.

    startPin = 24;
    for ( int bit = dataLength - 1; bit >= dataLength - 8; bit--) {
      //pinMode(startPin, OUTPUT);
      digitalWrite(startPin, (bitRead(Data, bit)));

      if (DEBUG) {
        Serial.print(" ==> startPin = " + String(startPin) + " ==> bit = " + String(bit));
        int value = bitRead(Data, bit);
        Serial.println(" ==> The read bit value = " + String(value));
      }
      // do next pin
      startPin += 2;
    }

    //  Step 3. Generate NotWrite and UpdatePulse signals.
    Serial.println("Write Pulse Executed");
    NotWritePulse();

    // Step 4. Setup for next Address byte, Data byte, and Write Command.
    Address = Address << 8;
    Data = Data << 8;
  }
  Serial.println("Update Pulse Executed");
  UpdatePulse();
}// End SetAddressAndData
}//End Loop


The file attached has the printout of the order that the address and data are setup, 
called Display for POST.  It contains the Serial output data to screen
The first 6 bits are the Address bits A5->A0
The second 8 bits are the Data bits D7 -> D0

It did not fit any more in this POST so I had to use an Attachment, sorry.

Display for POST.txt (9.22 KB)

loop{
void setAddressAndData(uint64_t Address, uint64_t Data, uint8_t Length, String Setter)

This is not Pascal. You can't define a function inside of a function.

-jim lee

I don't understand? this code works on Arduino due as you can see in the attachment which is a printout that the function produced and it is not pascal. Is there an extra } or { somewhere, which may be possible since I did some manual manipulation to get it fit in the available space!!

Please elaborate
Thanks

This is not the code you are running. It doesn't compile over here.

-jim lee

I got it, I used the definition in my "sample code" I changed it so that it should compile at least. There are not enough characters to show the complete code, plus that would be confusing to go through for just this section of the code.
Mel

Hi,
What DDS module? specs/data?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

How about some code that compiles?
For example, where are these Pin variables defined?

 // Write Pin
  pinMode(writePulsePin, OUTPUT);
  // Read Pin
  pinMode(readPulsePin, OUTPUT);
  // Reset Pin
  pinMode(resetPin, OUTPUT);
  // Update Pin
  pinMode(updatePin, OUTPUT);
  pinMode(24, UTPUT);

Please post your complete code.
If it is too big to put in code tags, then attach it.

Thanks.. Tom.. :slight_smile:

OK I just rewrote the section that i needed verified if I'm doing it right.

void setAddressAndData(uint64_t Address, uint64_t Data, uint8_t Length, String Setter);
  uint64_t Address = 4;
  uint64_t Data = 255;
  uint8_t Length = 8;
  String Setter = "CReg";
  bool DEBUG = true;
  constexpr int updatePin = 35;
  constexpr int resetPin = 22;
  constexpr int readPulsePin = 39;
  constexpr int writePulsePin = 37;
  int times = 1;

void setup() {
  // put your setup code here, to run once:
    // Set the Mode of the Address and Data pins
  pinMode(23, OUTPUT);
  pinMode(25, OUTPUT);
  pinMode(27, OUTPUT);
  pinMode(29, OUTPUT);
  pinMode(31, OUTPUT);
  pinMode(33, OUTPUT);
  pinMode(24, OUTPUT);
  pinMode(26, OUTPUT);
  pinMode(28, OUTPUT);
  pinMode(30, OUTPUT);
  pinMode(32, OUTPUT);
  pinMode(34, OUTPUT);
  pinMode(36, OUTPUT);
  pinMode(38, OUTPUT);
  // Write Pin
  pinMode(writePulsePin, OUTPUT);
  // Read Pin
  pinMode(readPulsePin, OUTPUT);
  // Reset Pin
  pinMode(resetPin, OUTPUT);
  // Update Pin
  pinMode(updatePin, OUTPUT);
  Serial.begin(9600);
  while(!Serial){};
} //end setup

void loop() {

  if (times == 1)
  {
    setAddressAndData(Address,  Data,  Length,  Setter); 
    times += 1;
  }
}

void setAddressAndData(uint64_t Address, uint64_t Data, uint8_t Length, String Setter) 
{
  if (DEBUG) Serial.println( " Set function = " + Setter); 
  int addLength = Length;
  int dataLength = Length;

  if (DEBUG) {
    Serial.println(" addLength = " + String(addLength));
    Serial.println(" dataLength = " + String(dataLength));
  }
  //   since if there are 6 addresses there will also be 6 data segments. The
  //   length of the address will be equal to the the sizeof the Address.
  //   The number of bytes in an address will equal the size of the Address


  // numBytes is same for Data as for Address
  int numBytes = Length / 8;

  //   The code will be setting the pin direction to output. then for each bit
  //   in the address or Data; we will set the pin value to either 0 or 1
  //   depending on the pin position in the Data or Address. I did not use
  //   the DDR's directly for this operation since the pins were located on
  //   different ports which would have made iteration a nightmare and in the
  //   end waste even more memory.
  
  for ( numBytes; numBytes >= 1; numBytes--)
  {
     //  Step 1. Generate the Addresses
     //  The startPin values come from the board Arduiono Due from the parallel
     //  port consisting of bits 20 - 55 of which we use 24 - 38 all even. 23 - 33 all odd
     //  are the address bits, data comes from the even bits.
     
    if (DEBUG) Serial.println(" ==> numBytes = " + String(numBytes));
    int startPin = 23;
    
    //  Main loop for the Address setup

    //  addLength - 3 since we want to start with the 6th bit per byte
    //  hence 48 - 1 to get actual bit position - 2 since that there are
    //  only 6 bits in each address hextuplt. i.e, Instead of starting at
    //  bit 47, 45 is the start point and it ends at 40. 45 to 40 inclusive are
    //  6 bits.

    for ( int bit = addLength - 3; bit >= addLength - 8; bit--) {
      //pinMode(startPin, OUTPUT);
      digitalWrite(startPin, (bitRead(Address, bit)));

      if (DEBUG) {
        Serial.print(" ==> startPin = " + String(startPin) +" ==> bit = " + String(bit));
        int value = bitRead(Address, bit);
        Serial.println(" ==> The read bit value = " + String(value));
      }
      startPin += 2;
    }

    // Step 2. Generate the Data segments
    // The startPin values come from the board Arduiono Due from the parallel
    // port consisting of bits 20 - 55 of which we use 23 - 41. 24 - 38 are the
    // data bits.  37 is the NotWrite pin and 39 is the Read pin. The boards 
    // Read not and Not Write did not align with the DDS pin out that's why it was 
    // generated separately.

    if (DEBUG) Serial.println(" ==> numBytes = " + String(numBytes));

    // Main loop for the Data setup

    // Data - 1 since we want to start with 47th byte hence 48 - 1 to get the
    // actual bit position since there are 8 bits in each Data byte. i.e,
    // Starting at bit 47, it ends at 40. 47 to 40 inclusive are 8 bits.

    startPin = 24;
    for ( int bit = dataLength - 1; bit >= dataLength - 8; bit--) {
      //pinMode(startPin, OUTPUT);
      digitalWrite(startPin, (bitRead(Data, bit)));

      if (DEBUG) {
        Serial.print(" ==> startPin = " + String(startPin) + " ==> bit = " + String(bit));
        int value = bitRead(Data, bit);
        Serial.println(" ==> The read bit value = " + String(value));
      }
      startPin += 2;
    }

    //  Step 3. Generate NotWrite and UpdatePuklse signals.
    Serial.println("Write Pulse Executed");
    NotWritePulse();

    // Step 4. Setup for next Address byte, Data byte, and Write Command.
    Address = Address << 8;
    Data = Data << 8;
  }
  Serial.println("Update Pulse Executed");
  UpdatePulse();
}

void UpdatePulse() 
{
  // Updates the DDS to the newly set data. 
  // Pin 14 of the board is the DDS input pin. 
  // Pin 14 matches Master Reset on DDS board.

  digitalWrite(updatePin, LOW);
  digitalWrite(updatePin, HIGH);
  delayMicroseconds(10);
  digitalWrite(updatePin, LOW);
}

void NotWritePulse() 
{
  // Pin 37 of the board is the not-Write pin. The boards Read-not and not-Write 
  // did not align with the DDS pinout that's why it was generated separately.
  // Pin 37 matches /WR on DDS board.

  digitalWrite(writePulsePin, HIGH);
  digitalWrite(writePulsePin, LOW);
  delayMicroseconds(10);
  digitalWrite(writePulsePin, HIGH);
}

This is the prtintout for the SetAddressAndData function

Set function = CReg
 addLength = 8
 dataLength = 8
 ==> numBytes = 1
 ==> startPin = 23 ==> bit = 5 ==> The read bit value = 0
 ==> startPin = 25 ==> bit = 4 ==> The read bit value = 0
 ==> startPin = 27 ==> bit = 3 ==> The read bit value = 0
 ==> startPin = 29 ==> bit = 2 ==> The read bit value = 1
 ==> startPin = 31 ==> bit = 1 ==> The read bit value = 0
 ==> startPin = 33 ==> bit = 0 ==> The read bit value = 0
 ==> numBytes = 1
 ==> startPin = 24 ==> bit = 7 ==> The read bit value = 1
 ==> startPin = 26 ==> bit = 6 ==> The read bit value = 1
 ==> startPin = 28 ==> bit = 5 ==> The read bit value = 1
 ==> startPin = 30 ==> bit = 4 ==> The read bit value = 1
 ==> startPin = 32 ==> bit = 3 ==> The read bit value = 1
 ==> startPin = 34 ==> bit = 2 ==> The read bit value = 1
 ==> startPin = 36 ==> bit = 1 ==> The read bit value = 1
 ==> startPin = 38 ==> bit = 0 ==> The read bit value = 1
Write Pulse Executed
Update Pulse Executed

TomGeorge:
Hi,
What DDS module? specs/data?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom.. :slight_smile:

Please...

pamam:
OK I just rewrote the section that i needed verified if I'm doing it right.

Needs more }

Please post your complete code.
If it is too big to put in code tags, then attach it.

Hi,
If your code is so big, have you got code that JUST writes to the DDS?
If you wrote your project in stages and got each stage to work before combining together, then you must have some JUST DDS code.

Tom... :slight_smile:

pamam:
OK I just rewrote the section that i needed verified if I'm doing it right

Set function = CReg

addLength = 8
dataLength = 8
==> numBytes = 1
==> startPin = 23 ==> bit = 5 ==> The read bit value = 0
==> startPin = 25 ==> bit = 4 ==> The read bit value = 0
==> startPin = 27 ==> bit = 3 ==> The read bit value = 0
==> startPin = 29 ==> bit = 2 ==> The read bit value = 1
==> startPin = 31 ==> bit = 1 ==> The read bit value = 0
==> startPin = 33 ==> bit = 0 ==> The read bit value = 0
==> numBytes = 1
==> startPin = 24 ==> bit = 7 ==> The read bit value = 1
==> startPin = 26 ==> bit = 6 ==> The read bit value = 1
==> startPin = 28 ==> bit = 5 ==> The read bit value = 1
==> startPin = 30 ==> bit = 4 ==> The read bit value = 1
==> startPin = 32 ==> bit = 3 ==> The read bit value = 1
==> startPin = 34 ==> bit = 2 ==> The read bit value = 1
==> startPin = 36 ==> bit = 1 ==> The read bit value = 1
==> startPin = 38 ==> bit = 0 ==> The read bit value = 1
Write Pulse Executed
Update Pulse Executed

Looks right to me. It sets the six Address bits to 4 and the eight Data bits to 255 and then pulses the Write pin LOW. As long as you are writing one byte into one address it looks good.

I'm a bit confused about the use of "Length" and "Setter". I also don't know why you are using a 64-bit variable for a 6-bit Address or a 64-bit variable for 8-bit data.

I would have written it like this:

void writeByte(byte Address, byte Data)
{
  if (DEBUG)
  {
    Serial.print("Writing ");
    Serial.print(Data);
    Serial.print(" into address ");
    Serial.println(Address);
  }

  // Set the six address pins to the address.  LSB is pin 33. MSB is pin 23.
  for (bit = 0; bit < 6; bit++)
  {
    byte pin = 33 - (2 * bit);

    //  Main loop for the Address setup
    digitalWrite(pin, bitRead(Address, bit));

    if (DEBUG)
    {
      Serial.print(" ==> pin = ");
      Serial.print(pin);
      Serial.print(" ==> bit = ");
      Serial.print(bit);
      Serial.print(" ==> The read bit value = ")
      Serial.println(bitRead(Address, bit));
    }
  }

  // Set the eight data pins to the data.  LSB is pin 38. MSB is pin 24.
  for (int bit  = 0; bit < 8; bit++)
  {
    pin = 38 - (bit * 2);
    //pinMode(startPin, OUTPUT);  // For WRITE, set to OUTPUT, for READ set to INPUT
    digitalWrite(pin, bitRead(Data, bit));

    if (DEBUG)
    {
      Serial.print(" ==> pin = ");
      Serial.print(pin);
      Serial.print(" ==> bit = ");
      Serial.print(bit);
      Serial.print(" ==> The write bit value = ")
      Serial.println(bitRead(Data, bit));
    }
  }

  //  Step 3. Generate NotWrite and UpdatePulse signals.
  Serial.println("Write Pulse Executed");
  NotWritePulse();
}

Hi again,

Thanks for the input.

I'm writing one byte at a time, even when the data and address is 6 bytes long. So at least that is OK. My address values can be as long as 48 bits so what I've done is progressively shifted the 48 bit to the left 8 bits at a time. My pin numbers don't change from the values 23-33 and 24-38 for address and data respectively. That way I don't have to change the for loops for every next byte. I know I did not specify that I would be using 48 bits as well as 8 bits (my bad) but that is why the uint64_t is used in my code in order to accommodate those values. Also as I shift the values 8 bits to the left the same bit numbers are always in play. The Length specifies the starting bit value e.g. 48 for a 6 byte word in the 64 bit address or data value. There is no unt48_t, I wish there was.
The main thing I was after was the setting up of the pins for address and data. I was not sure if these could change because of some characteristics of the independent setting of pins and then doing a write. I glad to hear that it should work; but sad to say that I think I may have destroyed my DDS Module since I see the address pin on the DDS connector go high and low when it should. All I'm doing is trying to set the frequency that I want after the default state of the DDS has finished, but it is not working.
I need to get another DDS Module after some more investigation into why it is not working.

Thanks again.
Mel

P.S. These sessions are great because it makes my brain rehash things with a different perspective. I've always worked with a friend for years where He and I would toss ideas around until we came up with a solution. He was an engineer from the Eindhoven University of Technology in the Netherlands, He had a brilliant mind.

My address values can be as long as 48 bits so what I've done is progressively shifted the 48 bit to the left 8 bits at a time.

uint8_t bytes[6];   // Your 48 bits..

for(int i=0;i<6;i++) {
   doSomethingWithByte(bytes[i]);
}

Wouldn't just doing this do the same thing for you?

-jim lee

It would be great if I needed an array of data. My data is in integer format for example, I start with the addresses of 04Hex, .. 09Hex then convert that into 4419622471689 which is an integer that contains the addresses so that each byte address is in consecutive bytes in the Address. If I start at address 04 (00000100) and so that when I shift the Address 8 bits to the left or 05 then (00000101) etc. till 09 will take its place. Check out the attached code if you want.

DDS_Frequency_Generator.ino (37.7 KB)

pamam:
My address values can be as long as 48 bits

I wonder how they fit 281 trillion addresses into a single chip.
It would sure help my understanding to know what DDS chip you are using.

johnwasser:
I wonder how they fit 281 trillion addresses into a single chip.
It would sure help my understanding to know what DDS chip you are using.

Oh that's easy! They use smaller fonts. I hear there's special tiny fonts just for doing this.

-jim lee

I guess you don't get it. There are 6 separate addresses within that 48 bit integer and you load the 48 bit data one address at a time. They are loaded into a buffer which then loads them using the update clock The DDS uses AD9854 see attachment.

AD9854 CMOS 300 MSPS Quadrature Complete DDS.pdf (1.18 MB)

Sorry I got the wrong file. This attachment is the right one, the other is the evaluation board data sheet.

AD9854 CMOS 300 MSPS Quadrature Complete DDS.pdf (1.18 MB)

OK, remember I said that these sessions are great for getting a new perspective on what you are doing.
Well I found that to verify the output to the pins I was reading the Address bits instead of the pin numbers.

int value = bitRead(Data, bit); is what I have but I s/h

int value = digitalRead(startPin); instead. Changing now and seeing if everything still works as it should.

Thanks Guys this should be interesting
Mel

That was quick and interesting because I got the same results. I was reading the value from Address and setting the pin output with it, then I was reading the value again from Address to validate it was correct. Duh, I should have read the pin back not the Address. I made the change and it actually was the correct value that the pin had so I'm now sure that the setup works. Isolation is coming down to the DDS Module.

Checked the outputs/inputs on the DDS they are all 3.3VDD now it's time to check the DUE outputs. If they are 5vs I'm spiraled, or rather my DDS is spiraled.

Thanks Y'all.
I'll let you know what I find. Luckily the modules are only $46.
Mel