|  From: Unknown 
Date: 1998-05-20 
Subject: TED timing 
 |  
Hello all! 
 
Here are my TED timing measurements, last touched Aug 24, 1996, as it seems.  I wrote the measurement program and most of this text in September 1995, and only updated the beginning of the text in 1996, 
the part about the cycles/frame value when double clock is used. 
 
Note that you need at least a 135 columns wide display to see the cycle diagram correctly. 
 
 Marko Mäkelä 
 
MOS 8360R2 TED timing in PAL-B mode 
 
Chip markings: 
 Top side: 
    MOS 
   8360R2 
    5084 
 Bottom side: 
   KOREA 
   AH483111 
    3 
 
Processor cycles per frame: 
 
clock   blanked  cycles/ 
type    screen   frame    remarks 
------  -------  -------  ----------- 
single  yes      17784    57 cycles/line * 312 lines/frame single  no       15634    57*312 - 43 cycles/badline * 25 rows * 2 badlines/row double  yes      34008    109 cycles/line * 312 lines/frame double  no       22882    109 cycles/overscan line * 108 overscan lines/frame + 
                          22 cycles/badline * 50 badlines + 
                          65 cycles/graphics line * 154 graphics lines 
 
The last value might change if you move the screen origin.  The video chip seems to switch to 1MHz mode on raster line 0, even if the graphics begins at a later line, like line 4 in the measurement above.  Moving the screen down would perhaps decrease the amount of free cycles. 
 
The timing diagrams are not too readable, especially if your screen is not wide enough.  The lines are meant to be checked against the $ff1e value line and the cycle number line.  "blank" is simply a normal overscan line.  "Line3" is the raster line #3.  The special about it is that it is a bad line and an overscan line at the same time. 
 
"Bad" denotes any bad line.  The TED has two badlines per character line, as it needs to fetch the character images as well as their colors from normal memory.  One of these badlines occurs at the last scanline of the previous character row, the other is at the beginning of the current character row.  At $FF06 = $xB the first bad line is 3, 
followed by 4, the first scanline of the first character row. 
 
As you might guess, "gfx" denotes any non-overscan non-badline, i.e. 
a graphics or text line. 
 
The cycle data at the end of the diagram lines list the amount of processor clock cycles in double and single clock modes. 
 
blank DxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxDxrxrxrxrxrxDxDxDxDxDxDx (109/57 cycles) 
 
line3 DxDx?X?X?X?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?xrxrxrxrxrxDxDxDxDxDxDx (22/14 cycles) 
 
bad   DxDx?X?X?X?cgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgcgxrxrxrxrxrxDxDxDxDxDxDx (22/14 cycles) 
 
gfx   DxDx?x?x?x?xgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxgxrxrxrxrxrxDxDxDxDxDxDx (65/57 cycles) 
 
ff1e  cc c c d d d d e 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9 a a a a b b b b c 
      46 a e 2 6 a e 2 2 6 a e 2 6 a e 2 6 a e 2 6 a e 2 6 a e 2 6 a e 2 6 a e 2 6 a e 2 6 a e 2 6 a e 2 6 a e 2 6 a e 2 
 
cycle 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 
      1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 
 
D=double clock (x in double clock mode, ? in single clock mode) 
?=read from somewhere (address unknown) 
r=memory refresh (address unknown, maybe zeropage) 
g=graphics fetch c=color or character code fetch x=bus free for processor 
 
The addresses of the "?" and "r" cycles need to be revealed.  They must be in the $0000-$3fff or $c000-$ff3f range.  My guess is that they are both on the zero page, i.e. at $0000-$00ff. 
 
Appendices 
 
Appendix A. Measurement program binary (single clock mode) 
 
begin 644 tedscan.single M`1`*$,L'GC0Q,#D```"@`(2AJ4"JAJ*1H<C0^SAI`.:B$/28D:'(T/KFHLK0 
M]::NT`*B"*D!J""Z_ZD(HI.@$2"]_ZD`A8RI&(6-J0F%CJ6.I*N(.&E`D:@ 
M:1"IC*:=I)X@V/_&CA#F8'BEC@H*"@H*"02-"_^I`2J-"O@Y1"EC(6=I8V% 
MGJ``A*&$HJD0C1+_J4"-%/^I`*+](,X0#A+_#A3_(-00J1ZB_R#.$*D=HO@ 
MSA#FH=#4YJ*EHLD(D,RI!(T2_ZD/C13_3!81C8,1CH01I9_%G_#I:"1G>:= 
MT`+FGF"M%`.N%0/),M`$X!'P#WB%HX:DJ3*B$8T4`XX5`ZD[C0;_J0B-!_^I MUXT3_X)_UA@>*G5C1/_J1N-!O^I"(T'_Z6CC10#I:2-%0-88*T>_TI*..DV M2?_)")`$2&@I!D$D`0D)"D#R0*P`+``2K``YI_N&?^EH:H)^*BEHH6@BD:@ 
M:D:@:D:@:JKHCGP1H@?($`#*$/JB`*6@RM#[K1[_A:#.&?_."?]HJ&BJ:$!4 
'24U)3D<M0:KH 
` 
end 
 
Appendix B. Measurement program binary (double clock mode) 
 
begin 644 tedscan.double M`1`*$,L'GC0Q,#D```"@`(2AJ4"JAJ*1H<C0^SAI`.:B$/28D:'(T/KFHLK0 
M]::NT`*B"*D!J""Z_ZD(HIR@$2"]_ZD`A8RI&(6-J1*%CJ6.I*N(.&E`D:@ 
M:1"IC*:=I)X@V/_&CA#F8'BEC@H*"@H)!(T+_ZD!*HT*_R#D$*6,A9VEC86> 
MH`"$H82BJ1"-$O^I0(T4_ZD`HOT@S1`.$O.%/@TQ"I'J+_(,T0J1VB_R#- 
M$.:AT-3FHJ6BR0B0S*D$C1+_J0^-%/],%1&-AQ&.B!&EG?/REH)&=YIW0 
M`N:>8*T4`ZX5`DQT`3@$?`/>(6CAJ2I,:(1C10#CA4#J3N-!O^I"(T'_ZG7 
MC1/_S@G_6&!XJ=6-$_^I&XT&_ZD(C0?_I:.-%`.EI(T5`UA@K1[_2DHXZ39) 
M_D(D`1(:"D'R020!"0D*0/)`K``L`!*L`#FG^X9_Z6AJ@GXJ*6BA:"*1J!J M1J!J1J!JJNB.@!&IU8T3_Z('R!``RA#ZH@"EH,K0^ZT>_X6@SAG_S@G_J=>- 
0$_]HJ&BJ:$!424U)3D<N0:(' 
` 
end 
 
Appendix C. Measurement program source code (dasm format) 
--8<--cut-here--8<--cut-here--8<--cut-here--8<--cut-here--8<--cut-here--8<-- 
  processor 6502 
 
single = 1 ; crystal / 20 
double = 2 ; crystal / 10 
clock = double ; select processor clock mode 
 
; KERNAL definitions fnlen = $ab ; length of current file name fnadr = $af ; pointer: current file name fa = $ae ; current device number cinv = $314 ; IRQ vector setlfs = $ffba setnam = $ffbd save = $ffd8 
 
area = $1800 ; start of data area 
 
; zero page variables saveptr = $8c ; pointer to save area samplenr = $8e ; number of sample 
 
samplept = $9d ; sample pointer chg = $9f ; indicates that a raster interrupt occurred ret = $a0 ; returned value pos = $a1 ; raster position (2-byte 11-bit integer (0-$7ff)) 
oldirq = $a3 ; placeholder for old irq vector 
 
  .org $1001 
basic: 
  .word 0$ ; link to next line 
  .word 1995 ; line number 
  .byte $9E ; SYS token 
 
; SYS digits 
 
  .if (* + 8) / 10000 
  .byte $30 + (* + 8) / 10000 
  .endif 
  .if (* + 7) / 1000 
  .byte $30 + (* + 7) % 10000 / 1000 
  .endif 
  .if (* + 6) / 100 
  .byte $30 + (* + 6) % 1000 / 100 
  .endif 
  .if (* + 5) / 10 
  .byte $30 + (* + 5) % 100 / 10 
  .endif 
  .byte $30 + (* + 4) % 10 
 
0$: 
  .byte 0,0,0 ; end of BASIC program 
 
start: 
  ldy #0 ; initialize the memory ($4000-$7fff) 
  sty pos 
  lda #$40 
  tax 
  stx pos+1 
fill$: 
  sta (pos),y 
  iny 
  bne fill$ 
  sec 
  adc #0 
  inc pos+1 
  bpl fill$ 
 
fill2$:  ; initialize the memory ($8000-$bfff) 
  tya 
  sta (pos),y 
  iny 
  bne fill2$ 
  inc pos+1 
  dex 
  bne fill2$ 
 
files:  ; set up files 
  ldx fa 
  bne faok$ 
  ldx #8 ; default device number faok$: 
  lda #1 
  tay 
  jsr setlfs ; set file numbers 
  lda #fnend-fname 
  ldx #<fname 
  ldy #>fname 
  jsr setnam ; and file name 
 
  lda #<area 
  sta saveptr 
  lda #>area 
  sta saveptr+1 
#if clock == single 
  lda #9 
#else 
  lda #18 
#endif 
  sta samplenr sample: 
  lda samplenr 
  ldy fnlen 
  dey 
  sec 
  adc #$40 
  sta (fnadr),y ; set the last file name letter 
  jsr measure 
  lda #saveptr 
  ldx samplept 
  ldy samplept+1 
  jsr save 
  dec samplenr 
  bpl sample 
  rts 
 
measure: 
  sei  ; set raster interrupt position 
  lda samplenr 
#if clock == single 
  asl 
#endif 
  asl 
  asl 
  asl 
  asl 
  ora #4 
  sta $ff0b 
  lda #1 
  rol 
  sta $ff0a 
  jsr install ; install the interrupt routine 
 
  lda saveptr ; initialize the memory pointers 
  sta samplept 
  lda saveptr+1 
  sta samplept+1 
  ldy #0 
  sty pos ; and the raster position 
  sty pos+1 
 
loop$: 
; first sample: read the high address byte 
  lda #$10 
  sta $ff12 ; set graphics bitmap origin at $4000 
  lda #$40 
  sta $ff14 ; set colormap origin at $4000 
  lda #<$fd00 
  ldx #>$fd00 ; read from $fd00 
  jsr dosample 
 
; second sample: read the low address byte 
  asl $ff12 ; set graphics bitmap origin at $8000 
  asl $ff14 ; set colormap origin at $8000 
  jsr redosample 
 
; third sample: read horizontal raster beam position 
  lda #<$ff1e 
  ldx #>$ff1e 
  jsr dosample 
 
; fourth sample: read vertical raster beam position 
  lda #<$ff1d 
  ldx #>$ff1d 
  jsr dosample 
 
; increment raster position (up to $800) 
  inc pos 
  bne loop$ 
  inc pos+1 
  lda pos+1 
  cmp #8 
  bcc loop$ 
 
; restore the normal video banking and return to main program 
  lda #4 
  sta $ff12 ; allow the TED to read from ROM again 
  lda #$f ; restore text/color map to $800 
  sta $ff14 
 
  jmp deinstall ; deinstall the interrupt routine 
 
dosample: 
  sta scan+1 
  stx scan+2 
redosample: 
  lda chg ; wait until it has been measured wait$: 
  cmp chg 
  beq wait$ 
  lda ret 
  sta (samplept),y 
  inc samplept 
  bne noinc$ 
  inc samplept+1 
noinc$ 
  rts 
 
install: ; install the raster routine 
  lda cinv      ; check the original IRQ vector 
  ldx cinv+1 ; (to avoid multiple installation) 
  cmp #<irq 
  bne irqinit 
  cpx #>irq 
  beq skipinit irqinit: 
  sei 
  sta oldirq ; store the old IRQ vector 
  stx oldirq+1 
  lda #<irq 
  ldx #>irq 
  sta cinv ; set the new interrupt vector 
  stx cinv+1 
skipinit: 
  lda #$3b ; select video mode (graphics) 
  sta $ff06 
  lda #$08 
  sta $ff07 
  lda #$d7 
  sta $ff13 ; select single clock 
  dec $ff09 ; acknowledge any pending interrupts 
  cli 
  rts 
 
deinstall: 
  sei  ; disable interrupts 
  lda #$d5 
  sta $ff13 ; enable double clock 
  lda #$1b 
  sta $ff06 ; restore text screen mode 
  lda #$08 
  sta $ff07 
  lda oldirq 
  sta cinv ; restore old IRQ vector 
  lda oldirq+1 
  sta cinv+1 
  cli 
  rts 
 
; Raster interrupt irq: 
; irq (event)   ; > 7 + at least 2 cycles of last instruction (9 to 16 total) 
; pha           ; 3 
; txa           ; 2 
; pha           ; 3 
; tya           ; 2 
; pha           ; 3 
; sta $fdd0 ; 4 
; jmp $ce00 ; 3 
; tsx           ; 2 
; lda $0104,x   ; 4 
; and #$10      ; 2 
; bne           ; 2 
; jmp ($314)    ; 5 
                ; --- 
                ; 44 to 51 cycles delay at this stage 
  lda $ff1e 
  lsr 
  lsr 
  sec 
  sbc #54 
  eor #$ff 
  cmp #8 
  bcc 0$ 
  pha  ; yes, spend 8 extra cycles 
  pla 
  and #7 ; and reset the high bit 
0$: 
  cmp #4 
  bcc 1$ 
  bit $24 ; waste 4 cycles 
  and #3 
1$: 
  cmp #2 ; spend the rest of the cycles 
  bcs *+2 
  bcs *+2 
  lsr 
  bcs *+2 ; now it has taken a constant amount of cycles 
  ; from the beginning of the IRQ 
 
effect: 
  inc chg ; update the "raster interrupt occurred" flag 
  inc $ff19 ; change the screen color 
 
  lda pos ; calculate the required delays 
  tax 
  ora #$f8 
  tay 
  lda pos+1 
  sta ret 
  txa 
  lsr ret 
  ror 
  lsr ret 
  ror 
  lsr ret 
  ror 
  tax 
  inx 
  stx coarse$ 
#if clock == double 
  lda #$d5 
  sta $ff13 ; enable double clock 
#endif 
 
  ldx #7 
fine$:  ; fine-tuning delay (0 to 7 cycles) 
  iny 
  bpl delay1$ 
delay1$: 
  dex 
  bpl fine$ 
 
coarse$ = * + 1 ; coarse delay (multiples of 8 cycles) 
  ldx #0 
delay8$: ; delay 8 cycles in this loop 
  lda ret ; 3-cycle-delay 
  dex 
  bne delay8$ 
 
scan:  ; do the actual scanning 
  lda $ff1e 
  sta ret 
  dec $ff19 ; restore the screen color 
 
  dec $ff09 ; acknowledge the interrupt 
#if clock == double 
  lda #$d7 
  sta $ff13 ; restore single clock 
#endif 
  pla  ; return from interrupt 
  tay 
  pla 
  tax 
  pla 
  rti 
 
fname:  ; file name for measurement results 
#if clock == single 
  .byte "TIMING-A" ; processor clock crystal/20 selected 
#else 
  .byte "TIMING.A" ; processor clock crystal/10 selected 
#endif fnend: 
--8<--cut-here--8<--cut-here--8<--cut-here--8<--cut-here--8<--cut-here--8<-- 
 |  
  |   |   
 Copyright © Plus/4 World Team, 2001-2025. Support Plus/4 World on Patreon |