If I understand correctly, you want to output a synchronous serial bit
stream at 1 MHz. Something like this:
___ ___ ___
clk __/ \___/ \___/ \___⋅⋅⋅
______ _______ _______ ___
dat __D0__X___D1__X___D2__X___⋅⋅⋅
where the data bits come from the PC.
If you want this to be a continuous bit stream, it will not be easy to
generate on an Arduino Uno.
Receiving the data
Since the data comes from the PC, it comes presumably through the serial
link. You have to account for the fact that this link adds a start bit
and a stop bit to every byte. Thus, you have 10 bits on the wire
for every 8 bits of actual data. Since you have to sustain
1 Mb/s average of actual data, this means that you must configure
the serial port for at least 1.25 Mb/s. However, the only baud rate
higher that 1 Mb/s supported by the Arduino Uno is 2 Mb/s.
Does your PC support this baud rate? Is the communication reliable at
this speed?
If the speed is too high, I would suggest you try to have the PC send
the data as PCM at a lower speed, and have the Arduino handle the
PCM → PDM conversion.
Transmitting the data
This data format is very similar to an SPI transmission. Then, the SPI
hardware port seems like the easiest way to generate it. However, the
SPI transmitter on the Uno is not double-buffered. This means that you
have to wait for the current byte transmission to be finished before
providing the next byte to the SPI hardware. This in turn means that you
will inevitably have small delays between consecutive bytes, and one out
of every 8 clock cycles will be stretched beyond the expected
1 µs. If this unsteadiness is acceptable for your application, then
do use the SPI transmitter. If not, you will have to find another
solution.
The serial port on the Uno has a special mode of operation where it
behaves like a master SPI port. Unlike the actual SPI port, this port is
double-buffered, which makes it possible to send a continuous bit stream
with a steady clock. The problem is, you cannot use this mode for
transmission and at the same time use the serial port receiver in its
regular asynchronous mode. Thus you will not be able to receive the data
from the PC when using this mode. If you can manage to route the
PC → Arduino communication through SPI, this mode of operation
of the serial port may be a good choice.
If none of the options above works for you I suggest, as last resort, to
generate the bitstream entirely by software. The timings are tight, as
each level of the clock has to be held for only 8 CPU cycles. But
it is likely doable in hand-written assembly, provided that interrupts
are disabled. Here is roughly how I may try to do that:
in output, _SFR_IO_ADDR(PORT_OUT) ; save a copy of the port reg.
loop:
lds data, _SFR_MEM_ADDR(UDR0) ; load data from USART
; output bit 0
andi output, ~_BV(1) ; clear clock bit
bst data, 0 ; save data[0]
bld output, 0 ; load it into output[0]
; no delay needed here
out _SFR_IO_ADDR(PORT_OUT), output ; output
ori output, _BV(1) ; set the clock bit
delay 6 ; assumed to be a macro
out _SFR_IO_ADDR(PORT_OUT), output ; output
; output bit 1
andi output, ~_BV(1) ; clear clock bit
bst data, 1 ; save data[1]
bld output, 0 ; load it into output[0]
delay 4
out _SFR_IO_ADDR(PORT_OUT), output ; output
ori output, _BV(1) ; set the clock bit
delay 6
out _SFR_IO_ADDR(PORT_OUT), output ; output
; etc...
rjmp loop
The code above assumes the UART is synchronized with the output stream,
which will likely not be the case in reality. Your real application may
then be more complex, and you will have to make that extra complexity
fit within the delay slots above.
Note that if you handle the PCM → PDM conversion on the
Arduino the resulting code may end up being simpler, as you will be able
to read the UART at every loop iteration without worrying about
synchronization. I have written a program that does something very
similar a while ago, and I just pushed it to GitHub for you to take a
look: avr-dac: Turn an AVR into a 1-bit D/A converter. Note
that this program is meant to be usable on AVRs without a hardware UART.
It expects the PCM data to be fed in the fashion of a shift register.
Using the UART would make the program simpler.
loop
itself also takes a few cycle to get called. You could use direct port manipulation instead, which is a lot faster. But to run at 1Mhz, you only have 16 cycles to toggle the pin and run the loop, leaving you with nearly no time left to do anything else. Also other interrupts could occur and slow your loop at "random" intervals, giving you a unstable 1Mhz signal. That's why I'm suggesting using timers, as they run in parallel.