[TI ASM] port $11, weirdness on wikiTI

Got questions? Got answers? Go here for both.

Moderator: MaxCoderz Staff

King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

[TI ASM] port $11, weirdness on wikiTI

Post by King Harold »

WikiTI wrote:# 04 : Set X auto-decrement mode. Every read or write operation from the data port will cause the LCD's internal pointer to move up one row.
# 05 : Set X auto-increment mode. Every read or write operation from the data port will cause the LCD's internal pointer to move down one row. The TI-83+ expects the LCD to be in this mode for most display routines.
# 06 : Set Y auto-decrement mode. Every read or write operation from the data port will cause the LCD's internal pointer to move left one column.
# 07 : Set Y auto-increment mode. Every read or write operation from the data port will cause the LCD's internal pointer to move right one
So, why have X modes to do with up/down and Y with left/right?
How can that be true?
afaik, either one of the things it says in each line can be true, either 04 is X auto-decrement mode or "Every read or write operation from the data port will cause the LCD's internal pointer to move up one row".

Could someone explain this?
User avatar
tr1p1ea
Maxcoderz Staff
Posts: 4141
Joined: Thu 16 Dec, 2004 10:06 pm
Location: I cant seem to get out of this cryogenic chamber!
Contact:

Post by tr1p1ea »

When talking in terms of X/Y, it is simply flipped around for the LCD. Ignore what it says aboput X/Y and just take note of the description. If you want to write in columns, set X-Increment mode.
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."
Image
Image
King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

Post by King Harold »

Ok thanks

It really isn't logical though.. weird lcd...
King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

Post by King Harold »

This knowledge let the following GS interrupt, can it be optimized? (I'm huge fan of optimizing! :) )

btw, it works (yay)

PlotsScreen has the LSbit of each pixel, SavesScreen the MSbit.

Code: Select all

IntDat:	.relocate $9A9A
	di
	exx
	ex af,af'
	
	ld c,$10
	ld a,1
	out ($10),a
	ld a,$20      ;column zero
	call LCDwait
	out ($10),a
	add a,a      ;a = $40, z-adress zero
	call LCDwait
	out ($10),a
	add a,a     ;a = $80, row zero
	ld ixl,a     ;save row
	call LCDwait
	out ($10),a
	
	ld a,(counter)
	inc a
	and 3
	ld (counter),a
	
	ld b,7
	call LCDwait
	out (c),b
	
	;set left-to-right mode and start at 0,0
	ld hl,plotSScreen	;bit 0 of colour
	ld de,saveSScreen	;bit 1 of colour
	;	0:	white
	;	1:	light
	;	2:	dark
	;	3:	black
	ld b,12
	;ixl is row
	or a
	jr z,BlackOnly
	dec a
	jr z,DarkBlack
	dec a
	jr z,LightDarkBlack
	jr exit
BlackOnly:
-:	ld a,(de)
	and (hl)	;both (colour = 3)
	call LCDwait
	out ($11),a
	inc hl
	inc de
	djnz {-}
	ld b,12
	inc ixl
	ld a,ixl
	cp $C0
	jr z,Exit
	call LcdWait
	out ($10),a
	ld a,$20
	call LcdWait
	out ($10),a
	jr {-}
DarkBlack:
	ex de,hl
	ld e,$11
-:	call LCDwait
	ld c,e
	outi		;dark and black both have a set MSB, so that's the only thing you need to out
	jr nz,{-}
	ld b,12
	inc ixl
	ld a,ixl
	cp $C0
	jr z,Exit
	call LcdWait
	out ($10),a
	ld a,$20
	call LcdWait
	out ($10),a
	jr {-}
LightDarkBlack:
-:	ld a,(de)
	or (hl)	;any colour other than 0
	call LCDwait
	out ($11),a
	inc hl
	inc de
	djnz {-}
	ld b,12
	inc ixl
	ld a,ixl
	cp $C0
	jr z,Exit
	call LcdWait
	out ($10),a
	ld a,$20
	call LcdWait
	out ($10),a
	jr {-}
Exit:	ex af,af'
	exx
	ei
	reti
LCDwait:
	ld c,$10
-:	in (c)
	ret p
	jr {-}
Counter:	.db 0
	.endrelocate
IntDatEnd:
User avatar
tr1p1ea
Maxcoderz Staff
Posts: 4141
Joined: Thu 16 Dec, 2004 10:06 pm
Location: I cant seem to get out of this cryogenic chamber!
Contact:

Post by tr1p1ea »

Nice basic grayscale routine, making use of plenty of registers :).

The only problem is, well, your method is needlessly complex. With these basic grayscale routines you dont actually have to refer the contents of either buffer to one another since you never clear the screen etc.

You dont need seperate routines for black, darkgray (or darkblack as you put it hehe :)), lightgray or white.

All you do is display one buffer longer than you do the other. So the darkgray buffer would be displayed twice as long as the lightgray one (typically). This rids the need to AND any 2 bytes together to obtain the BLACK information since when you switch from displaying one buffer to the other, the exact same black pixels will be present anyway and thus the pixel state *for those pixels* on the LCD will not change. The exact same thing is true for any WHITE pixels as well. The only pixels on the LCD that will be changing state are your grays. The dark gray pixels will be displayed for 2/3 of the time, the light for 1/3 of the time, which is what you want.

So in light of this, your routine can be optimised a lot. You only need to use your counter to select which buffer to show each frame, then you only need a generic LCD update routine.

Sorry if the explanation is a little crude, i hope you get the idea.
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."
Image
Image
King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

Post by King Harold »

Oh yea I see, never thought of that lol thanx
I used DarkBlack (lol) because it prints both Black and Dark at that moment, but it does look a bit odd yes :wink:
King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

[TI ASM] grayscale

Post by King Harold »

I came up with the following code, but it's terribly flickery..
It doesn't trash ixl anymore (which the other code did, should have saved to ram but well..)

Code: Select all

_IntDat:	.relocate $9A9A
	di
	exx
	ex af,af'
	ld c,10h
	ld hl,_Dat
	ld b,5
-:	call _LCDwait
	outi
	jr nz,{-}
	ld e,$80
	dec d
	jr z,_Light
	ld hl,plotSScreen
	jr {+}
_Light:	ld hl,saveSScreen
	ld d,3
+:	
--:	ld b,12
-:	call _LCDwait
	inc c
	outi
	jr nz,{-}
	inc e
	ld a,e
	cp C0h
	jr z,_Exit
	call _LCDwait
	out (10h),a
	ld a,20h
	call _LCDwait
	out (10h),a
	jr {--}
	
_Exit:	ex af,af'
	exx
	ei
	reti
_LCDwait:
	ld c,10h
-:	in (c)
	ret p
	jr {-}
_Dat: .db 1,7,20h,40h,80h   ;these values are OUTed to 10h
	.endrelocate
_IntDatEnd:
User avatar
tr1p1ea
Maxcoderz Staff
Posts: 4141
Joined: Thu 16 Dec, 2004 10:06 pm
Location: I cant seem to get out of this cryogenic chamber!
Contact:

Post by tr1p1ea »

Yeah this method tends to be flickery, that why we had to come up with fast bit interlacing routines.

I see that your routine is nice and safe due to your lcdwait. Have you ever looked at the source to a typical FastCopy routine?
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."
Image
Image
King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

Post by King Harold »

Yes, but I the time lost to the safeness is worth it imo, a fixed 150 wait states wouldn't do any good on a 83p, and a fixed 60 would be bad for SE's in fast mode, and I didn't really want to disable fastmode..

in any case, that other routine (the bigger one) has absolutely no flicker at all, which is actually quite odd..
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Code: Select all

    call $B
is another safe LCD delay, so you don't have to roll your own.

See page 87 in the TI-83 Plus Developer Guide (for older 83+s there is a limitation of this function).

As well as an X and Y register, there is a Z register that corresponds to which row of data stored in RAM appears at the top of the physical LCD. Look in the official datasheet for more information.
User avatar
tr1p1ea
Maxcoderz Staff
Posts: 4141
Joined: Thu 16 Dec, 2004 10:06 pm
Location: I cant seem to get out of this cryogenic chamber!
Contact:

Post by tr1p1ea »

Were you testing this on hardware? The thing with grayscale routines is that they are very calc specific. Quite often it will look good on one calc, but it will flicker on another.
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."
Image
Image
King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

Post by King Harold »

Ben, I know, I set Z to 0 by outing 40h.
call $B messes with the X flag on 83+'s doesn't it?

In any case, my waiter isn't less safe, and it's additional delay is minimal >(4+12+11+10) wasted (in case that the LCD gets ready immediately after an in(c) ), which does not mean it's any better though.

Interlacing sounds interesting, how does it work?


Edit: the long routine flickers as well if you decide not to call it continuously and clear port 3, I expected no more, so how does interlacing work?
User avatar
Jim e
Calc King
Posts: 2457
Joined: Sun 26 Dec, 2004 5:27 am
Location: SXIOPO = Infinite lives for both players
Contact:

Post by Jim e »

First thing, all greyscale requires timing its the greatest judge of quality. I've test Truegrey, Rigview, and RGP, they all use 70hz for they're near flawless display. Check the wiki for port 3 and 4 for interrupt timings, you'll want to skip interrupts to get in the right area, this will also require counting tstates.


Don't use Call $b, its different across os versions, and worse yet EXTREMELY SLOW. the 84 it can waste upwards of 200 tstates for no good reason.

You should turn off the cpu speed, and use a set delay instead of waiting for the hardware. The reason is so you can accurately check the timing. Other wise you'll have no idea when it will generate an interrupt.

I wrote a guide on interlacing some where here, its gotta be floating on the board.
Image
King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

Post by King Harold »

Hm, I found loads of stuff about grayscale, but they didn't really get into interlacing, they only stated that you should do it.
Do you just mask everything and switch masks every time?

Edit: it doesn't look nearly as bad as on this screeny, but it give some idea as to how it looks, in reality it looks more like the dark area switches to light sometimes, and the light area switches to somewhere in between dark and light
Image
User avatar
tr1p1ea
Maxcoderz Staff
Posts: 4141
Joined: Thu 16 Dec, 2004 10:06 pm
Location: I cant seem to get out of this cryogenic chamber!
Contact:

Post by tr1p1ea »

Yeah that seems pretty typical.

With interlacing you just apply a mask to each byte, say %11011011 for example. The older method you would and this to the first byte, cpl it, then and it to the second byte (and or your results together). This would give you more information from the dark layer over the light layer, which you would out to the lcd. You could either rotate this mask for each byte, or you could use a series of masks like %01101101, %10110110 etc which are all equivalent to one another.
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."
Image
Image
Post Reply