First of all, if NTSC displays 60/1.001 fields per second (about 59.94), and it displays 262.5 lines per field, then this means that one line is displayed at a rate of (60*262.5)/1001 kHz, or 15.734 kHz. Taking the reciprocal of this value gives us the period, 0.063555 milliseconds or 63.555 microseconds if I've done my math correctly.
According to the laserdisc standard, a picture number stored in the VBI will span 48 microseconds because each bit is 2 microseconds long and that includes a transition from black to white or white to black. See https://www.daphne-emu.com:9443/mediawiki/index.php/VBIInfo for more information.
So my task is to figure out how many microseconds to delay after starting the proper line and then do a white/black transition every 1 microsecond as exact as I can. I probably will need to completely unroll a loop in assembly language on the AVR to avoid drift.
Here is a screenshot from my scope showing the first 19 lines of an NTSC field (generated from the raspberry pi).
So what is the easiest way to find where line 19 starts? Well, the LM1881 does have a pin called Composite Sync which may be able to help.
This shows the CSYNC signal. As you may be able to see, the signal is weak during the vsync pulse but strong everywhere else (this actually surprises me). My conclusion is that due to the relatively unreliable pulse the occurs during vsync, the CSYNC pulse cannot be relied upon exclusively to find where the proper line number starts.
My current approach is to wait for VSYNC (and/or FIELD transition) and then reset the AVR's cycle counter. Then on every CSYNC pulse, check the elapsed cycle count to determine whether I am on the correct line.
This actually seems to work pretty well (so far).
I was able to successfully isolate line 11 and inject a little white bar into it.
Here is how it looks when captured in VirtualDub:
In short, this is very promising! With some careful work I should be able to start putting in frame numbers on lines 17 and 18!