Generating a 16Mhz output with Arduino Due

Hi all!

I'm working on a project where I'm reverse engineering an old MDA graphic card and want to mimic the output to directly drive an old CRT I've got. I'd like to use arduino to generate the signal because I'm familiar with how it works, but a normal UNO won't cut it as the main data line for the graphics runs on 16,257Mhz exactly. That's why I'm considering to buy Arduino Due as it runs at 84MHz, but i wonder if it is capable of producing such an exact signal and at such high speeds.

Does anyone know if this is possible with an arduino Due? If not, does anyone know any other way to generate such a signal? :)

What is the waveform of the 16257000 Hz output signal ?

Buy one. https://www.digikey.com/products/en/crystals-oscillators-resonators/oscillators/172?k=oscillator&k=&pkeyword=oscillator&pv139=50&FV=ffe000ac&mnonly=0&newproducts=0&ColumnSort=0&page=1&stock=1&quantity=0&ptm=0&fid=0&pageSize=25

ard_newbie: What is the waveform of the 16257000 Hz output signal ?

The output form is a normal 0V to +5V square wave signal. Note; its not an constant on/off signal i want, i want to create a digital datastream that sends bits. So the output is several 1s and 0s depending on the data that gets send at 16.257Mhz (i guess i can call this the baud rate).

CrossRoads: Buy one. https://www.digikey.com/products/en/crystals-oscillators-resonators/oscillators/172?k=oscillator&k=&pkeyword=oscillator&pv139=50&FV=ffe000ac&mnonly=0&newproducts=0&ColumnSort=0&page=1&stock=1&quantity=0&ptm=0&fid=0&pageSize=25

This is just an crystal oscillator, i want to create a datastream as mentioned above.

So you want a burst of 16MHz to represent a 1, and a lack of a burst for a 0? Can use the oscillator and a AND gate to let the clock thru when an output pin goes high.

Or do you want the equivalent of SPI.transfer() where the clock is 16 MHz? (clock line + data line)

Or do you want the equivalent of Serial.print() where the bits can change every 62.5nS and the receiver samples the data at 62.5nS x 1.5 after seeing a low start bit to determine if the middle of the next and subsequent bits are a 1 or 0?

CrossRoads: So you want a burst of 16MHz to represent a 1, and a lack of a burst for a 0? Can use the oscillator and a AND gate to let the clock thru when an output pin goes high.

Or do you want the equivalent of SPI.transfer() where the clock is 16 MHz? (clock line + data line)

Or do you want the equivalent of Serial.print() where the bits can change every 62.5nS and the receiver samples the data at 62.5nS x 1.5 after seeing a low start bit to determine if the middle of the next and subsequent bits are a 1 or 0?

In this case, won't SPI and Serial be the same? besides from how the data is read?

Either way, the CRT screen samples the datastream with an inbuild 16.257mhz clock after its gets triggered by an external horizontal sync signal square wave signal that clocks at 18.432Khz (16.257Mhz / 882, there are 720 pixels across the screen + some retrace time resulting in 882).

So from what i understand its most simular to SPI without Slave Select and only the MOSI line.

"In this case, won't SPI and Serial be the same? besides from how the data is read? " No, SPI has 2 discrete line, clock & data. The receiver has a shift register and uses the master's clock output to move the bits into the shift register. Serial only has 1 line, with the receiver running its own clock for timing of the incoming signal.

"the CRT screen samples the datastream with an inbuild 16.257mhz clock after its gets triggered by an external horizontal sync signal square wave signal " Sounds more like Serial then, with starting bit derived from the sync bit.

Either way, that's the limit of my help, understanding what you are doing. I don't know how to do that with a Due. Good luck with the project. Maybe you'll have to change the Due's clock to be more compatible with the output speed you want.

but a normal UNO won't cut it as the main data line for the graphics runs on 16,257Mhz exactly. That's why I'm considering to buy Arduino Due as it runs at 84MHz, but i wonder if it is capable of producing such an exact signal and at such high speeds.

No 84MHz / 16.257 MHz = a division ratio of 5.16700498247 which is not possible with a simple digital division.

Can you divide 84,000,000 by 16,275,000 and have the result be an integer? I the answer is no, then the Due cannot divide down it's own clock to generate the signal you want.

What would happen if you could change the Due's clock to be 81,375,000hz? What is the answer repeating the above but substituting the new clock frequency?

After you change clock rate of the Due, you now know that the magic number is 5. That is the number of Due clock periods in one video clock pulse. Knowing that, ask youself this:

What computations do I need the Due to perform? Will I need to make decisions about turning bit stream going to the video device on or off on a cycle by cycle basis?

If the answer is yes, even the Due is not going to be fast enough for your needs. Why?? Because you cannot do much computationally with 5 clock cycles between decision points. I'm not saying that's a show stopper because I don't fully understand what you want to do but I hope it gives you enough to understand the challenges of directly creating video content.

Quite possibly better suited to a fast FPGA, don't know for sure.

avr_fred: After you change clock rate of the Due, you now know that the magic number is 5. That is the number of Due clock periods in one video clock pulse. Knowing that, ask youself this:

What computations do I need the Due to perform? Will I need to make decisions about turning bit stream going to the video device on or off on a cycle by cycle basis?

So far the plan is to just let the Due read from memory and spit out the datastream, so 5 cycles could be enough cycles to just read from the memory. But the question is more if the Due is at all capable to write to an I/O pin at that speed, preferably with arduino code.

It boils down to the fastest switching you can possibly do with arduino code:

int outPin = 50;

void setup() {

pinMode(outPin, OUTPUT); }

void loop() { digitalWrite(outPin, HIGH); // sets the pin on delayMicroseconds(1); // pauses for 1 microsecond digitalWrite(outPin, LOW); // sets the pin off delayMicroseconds(1); // pauses for 1 microsecond }

Since 1 microsecond is a millionth of a second, we are talking about a freq of half of 1 MHz here, i.e. 500kHz on an output pin, providing the delay is stable as such a low value, which it may not be.

What is the theoretical max output of the SAM3X processor at 84MHz?

It depends on the time it takes to set the pins high and low, and this is all found in the specs of clockcycles to do this and that. Assuming maximum efficiency with one cycle high and one cycle low, you would get 48MHz, and you could double this to 24MHz if waiting for two cycles, but you would never be able to take out a fifth of 84+MHz to get around 16.x - not as long as you want a 50% duty cycle of the square wave.

When I try the example above, I get a fairly decent square wave close to 50% duty cycle. Trying to take away the delay altogether, produces a shorter high, about half the 1 microsecond delay, with the low being around 1 microsecond. Clearly there is some overhead in the arduino code.

But the question is more if the Due is at all capable to write to an I/O pin at that speed,

So that will be a read / modify / write cycle, my guess is no.

so 5 cycles could be enough cycles to just read from the memory.

You sure, read from memory, do something with the contents, increment a pointer, decide if it is time to stop.
The only way I could see that working is if you used DMA.

I agree with avr_fred look at an FPGA.

 delayMicroseconds(1);

Is a bit useless because the microsecond clock only updates every 4uS.

This is the fastest I have seen a Due read / write

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}
inline int digitalReadDirect(int pin){
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}

void setup() {
pinMode(21,OUTPUT);
}
int a;
void loop() {
  while(1){
a = digitalReadDirect(22);  
digitalWriteDirect(21,HIGH);
a = digitalReadDirect(22);
digitalWriteDirect(21,LOW);
}
}
// there is a long overhead on the loop function giving a 420KHz cycle time
// putting it in a while loop gives a 6.4MHz cycle time
// see screen dumps inside this folder dump 2 using loop, dump3 using while
// dump 1 uses normal digital read / write commands

DS1Z_QucikPrint1.png

DS1Z_QucikPrint2.png

DS1Z_QucikPrint3.png

Grumpy_Mike: This is the fastest I have seen a Due read / write // there is a long overhead on the loop function giving a 420KHz cycle time // putting it in a while loop gives a 6.4MHz cycle time // see screen dumps inside this folder dump 2 using loop, dump3 using while // dump 1 uses normal digital read / write commands

Well that more or less answers all of my questions.

So the conclusion is, no, an arduino Due isn't capable of creating a datastream of exactly 16.257MHz. I will start looking into FPGA's and how to use those. Thanks for the info!

I will start looking into FPGA's and how to use those.

OK but be aware that a FPGA is several orders of magnitude more difficult than an embedded micro, and that an Arduino embedded micro is about as easy as it comes.

Reverse engineering a gfx card to drive a monitor? Do you actually want to mimic the card and all its I/O or do you just want to drive a monitor?

DueVGA library allows to drive VGA as well as NTSC/PAL TV: https://stimmer.github.io/DueVGA/

Hermann. |500x375