[time-nuts] ANFSCD - Synchronizing time in home video recorders

kevin-usenet at horizon.com kevin-usenet at horizon.com
Wed Feb 15 23:50:39 UTC 2012


> It's possible to use Bresenham with two integers 10,000,000 and
> 32,768 but I found no way to perform all the 24-bit calculations
> on an 8-bit PIC quick enough. Removing the GCD often helps
> but in this case the accumulator remains 3-bytes wide.

Huh?  Dividing 10,000,000 by 4 (to match the PIC instruction timing)
and multiplying 32768 by 2 (since you have to generate both edges),
you want to generate an edge every 2500000/65536 instruction
cycles.

That's every 38 or 39 cycles.  To be precise, 38 instructions
most of the time and 39 instructions 9632/65536 of the time.

Since the divisor is a power of 2, this fits conveniently
into a 16-bit accumulator.  Let me see if I can put the code
together...

cblock 0x20
	gpcopy
	lsb
	msb
	tmp
endc

step	equ d'9632'

loop:				; Cycles at end of instruction
	comf	gpcopy,f	;  1
	movf	gpcopy,w	;  2
	movwf	GPIO		;  3

	movlw	8		;  4
	movwf	tmp		;  5
delay:
	decfsz	tmp,f		;  6, 9,12,15,18,21,24,27
	goto	delay		;  8,11,14,17,20,23,26

	nop			; 29

	movlw	step&0xff	; 30
	addwf	lsb, f		; 31
	movlw	step>>8		; 32
	skpnc			; 33
	  movlw	(step>>8)+1	; 34
	addwf	msb, f		; 35
	skpc 			; 36
	  goto	loop		; 38
	goto	loop		; 39

The minimum length of this loop is 12/13 cycles, but it depends on a
power-of-2 output frequency (after modulo reduction, so you could have
powers of 5 as well).

With some clever unrolling, it can be reduced to 10/11 cycles:
loop:
	clrf	GPIO		;  1

	movlw	step&0xff	;  2
	addwf	lsb, f		;  3
	movlw	step>>8		;  4
	skpnc			;  5
	  movlw	(step>>8)+1	;  6
	addwf	msb, f		;  7
	skpnc 			;  8
	  goto	$+1		; 10
	movlw	0xff		; 10/11

	movwf	GPIO		;  1
	movlw	step&0xff	;  2
	addwf	lsb, f		;  3
	movlw	step>>8		;  4
	skpnc			;  5
	  movlw	(step>>8)+1	;  6
	addwf	msb, f		;  7
	skpc 			;  8
	  goto	loop		; 10
	goto	loop		; 11

An arbitrary divisor will complicate this somewhat, but not actually
add very much time.  You just need two matched code paths, which add
"step", or "step + 65536-divisor" to the accumulator as appropriate.

There may also be some way to use higher-order Bresenham to reduce things
to 8 bits, at the expense of needing the subroutine stack.

Here, we have 38 instructions most of the time, and 39 instructions
9632/65536 = 301/2048 of the time.  That means that the pattern is
either 5x38+39 or 6x38+39, with the latter happening (2048%301)/301 =
242/301 of the time.

Since we have the 5x38+39 pattern happening 59/301 of the time, you
have 5x(6x38+39)+(5x38+39) some of the time, and 6x(6x38+39)+(5x38+39)
the rest of the time.  My brain is getting tangled figuring out which is
which, but it's one of them (301%59)/59 = 6/59 of the time and
the other 53/59 of the time.  You could use a 1-byte accumulator, or
just open-code that part of the pattern.




More information about the Time-nuts_lists.febo.com mailing list