Spent most of the day working with Rich on the caption decoder again. Probably won’t get to work on it any more before I return to California.
In the morning, Rich lugged his Tektronix 475A oscilliscope into the computer room, and things were coming together pretty well. There are debug conditionals to usurp an I/O pin to debug the timing of the DC restore signal and line 21 sampling. It didn’t take too long to get both timed correctly. The DC restore was happening a bit too early. The data sheet for the EL4581 sync separator gives a typical propogation delay of 260 ns for sync tips from the compositive video input to the composite sync output, and a maximum of 400 ns. No minimum was specified. The PIC interrupt latency is 3-4 cycles. (The PIC is deterministic at 3 cycles, but the composite sync input is completely asynchronous to the PIC clock, so one cycle jitter is introduced.) So I planned the timing based on 200-400 ns delay through the sync separator, and 600-800 ns interrupt latency.
It turns out that Rich designed the hardware with a low-pass filter between the video input and the PIC comparators, and the prop delay of the low-pass filter is very close to the prop delay of the EL4581, so I had to change the timing to accomodate that. In the process, I made the DC restore pulse 2.0 us wide rather than 1.6 us. The timing between the end of the DC restoration and the start of line 21 caption sampling was too tight, so I changed the code to not try to DC restore on line 21.
The scan line counting works a bit strangely due to the half-lines during the vertical blanking interval. In NTSC video, lines 1-3 and 7-9 have extra “serration” pulses in mid line, and lines 4-6 (the actual vertical sync) have two really wide sync pulses per line. The PIC is interrupted at the falling (leading) edge of every sync pulse, so it gets two interrupts on those lines. The interrupt handler tries to ignore the second pulse on those lines by delaying more than half a scan line, then resetting the interrupt flag again. But this only happens after the vsync pulse is detected.
On the first interrupt at which the vertical sync input from the EL4581 is low (but was previously high), the scan line counter has to be set. But this happens midway through line 4 of the odd field, so it can’t just be reset to 0. I had miscounted, so the code was trying to sample the caption data on line 22 instead of 21. Naturally, when I tried to fix this off-by-one error, I went the wrong direction and sampled on line 23. Then I fixed it. We had to fiddle with the counter for the even field as well. (Caption channels 1 and 2, and “text” 1 and 2 are in the odd field. Caption channels 3 and 4, “text” 3 and 4, and XDS are in the even field.)
So after success getting the timing right, which I expected to be the most difficult part of the process, I was dismayed to find that the serial I/O code was not working well at all.
Those of you who’ve been reading this story since the beginning will recall that one of the major reasons for doing this redesign using the PIC16F628A in place of the older PIC16C622 was to take advantage of the hardware UART, and eliminate the bit-banging code used in the old version. So things should be much simpler now, right?
I used the interrupt-driven circular-buffer serial routines out of my uarttest program (originally for the PIC16C64), though in this project I don’t use the actual UART interrupts, instead polling the interrupt in the composite sync interrupt handler. (This is done because handling a UART interrupt just before a composite sync pulse was about to happen would introduce unacceptable latency in the DC restoration and line 21 sampling.)
I was trying to test the serial I/O by having the PIC output a “*” character at startup, and sending it the “V” (version) command, which makes it send back a version and copyright notice. The version message was being sent back, but it was getting garbled. When actual caption samples were output in hexadecimal in debug mode, it was outputting lots of “F” digits, but not always the right number per line.
Later in the afternoon, after spending a bunch of time on miscellaneous other issues, I wasn’t getting any serial output at all, despite having made no changes to the serial I/O code! We spent 3-4 hours debugging this, and it doesn’t seem to be completely fixed yet. So far I’ve fixed the following problems in the code:
- The “xmit2″ routine that puts a character to be transmitted into the output queue was not saving the FSR register. This is the register used for indirect memory access. So anywere that called xmit2 from a loop using FSR, as was the case in the version messsage output, was really losing bigtime.
- The PIC16F628A RAM includes 16 bytes that are mirrored in all four register banks, at locations 0×070-0x07f, 0x0f0-0x0ff, 0×170-0x17f, and 0x1f0-0x1ff. A few critical variables such as the interrupt context save was being done to this area. We discovered purely by accident that 0×070 is reserved by the ICD2, and that was where my interrupt handler was storing W (the accumulator). Changing the origin of the interrupt variables to 0×071 made things a little bit more stable. The way we discovered that 0×070 (and its mirrors) are not available is that we opened the register window, and the hex value shown for 0×070 is “RR”. It took a while to figure out that this meant “reserved”. The ICD2 manual says that some chip resources are reserved, but doesn’t give details. Rich eventually found that the online help includes details of the reserved resources by chip, but doesn’t include those of the PIC16F627A/628A/648A. Location 0×070 and its mirrors were the only locations showing “RR”, but I think that’s because we’d told MPLAB that we’re using a PIC16F628A. The bond-out part is a PIC16F648A, which has more RAM, so the ICD2 is probably using some of those upper locations that don’t exist in a real PIC16F628A. We also found in the new ICD2 manual that it can’t be used to debug PIC18 programs that use the two-level priority interrupt capability of those parts. Doesn’t affect the caption decoder, since it’s not using a PIC18, but that explains why we could never get the ICD2 to work for debugging the Watts Up? Pro. Sigh.
- While studying the UART control register (RCSTA and TXSTA) values to see if it was configured correctly, I noticed that the USART documentation in the data sheet claimed that the direction (TRIS) register bits for BOTH transmit and receive need to be set, which would normally make those pins inputs. Makes sense for the RxD pin, but for TxD as well??? I vaguely remembered Rich telling me something about needing this on another PIC, so I tried it. Didn’t seem to help. Later discovered that it works OK regardles of the state of the TRIS bits, which matches what the logic diagram in the I/O port section of the data sheet suggests should happen.
- Discovered by accident that after the previous changes, the PIC really was sending serial output, but Minicom running on my laptop somehow wasn’t receiving it. Restarted Minicom, and my output started appearing. Not sure if the problem was with Minicom, the USB-serial converter, the Linux driver for the converter, or what. Sigh.
So the serial output is now working, but it still seems to drop some characters, and occasionally garble them. Pretty strange. I’ll have to do some more debugging when I get back to California.
It’s really aggravating that the parts that I expected to be difficult to debug were in fact easy, and the parts that should have been easy are taking a huge amount of time. So it goes…