### Author Topic: [TUTO] How to make "perfect" grayscale in Axe using multiple interrupts!  (Read 1862 times)

0 Members and 1 Guest are viewing this topic.

#### pimathbrainiac

• Occasionally I make projects
• Members
• LV10 31337 u53r (Next: 2000)
• Posts: 1731
• Rating: +136/-23
• dagaem
##### [TUTO] How to make "perfect" grayscale in Axe using multiple interrupts!
« on: March 25, 2013, 02:56:29 pm »
In the tradition of ThePenguin77 and Hayleia, I am making my grayscale EPIC!!!

So... Wabbit does not like my code , but it works on my calc, so hopefully it will work on yours!

Attached is the source (84+), to make it 83+, calculate the values necessary as shown in the tutorial. Speaking of which, here is my explaination/tutorial!:

Speed // 83+ // 84+
0 // 560 Hz // 512 Hz
2 // 248 Hz // 228 Hz
4 // 170 Hz // 146 Hz
6 // 118 Hz // 108 Hz

With multiple interrupts running at multiple speeds, you can have more data points than just one interrupt!

The problem: how do you make the data points sync up?

Here's how (set up for a basic RPG engine with only one 12*8 tilemap) (please excuse the direct cut-and-paste from graph link):

Code: [Select]
.CC51.000üE0.000üF108.000üJ0.000üT0üX0üY0üA0üBJ/*EüF0.211üK0.474üI0.740üLFnOff ClrDrawõõ[010101010101010101010101]üGDB1[010101010101010101010101][010101010101010101010101][010101010101010101010101][010101010101010101010101][010101010101010101010101][010101010101010101010101][010101010101010101010101][0000000000000000]üPic1[FFFFFFFFFFFFFFFF]For(Z,0,11)For(Á,0,7)Pt-On((Z*8),(Á*8),(8*{(Á*12)+Z+GDB1})+Pic1)õEndEndfnInt(DG,0)fnInt(DH,6)fnInt(DI,4)fnInt(DJ,2)Pause 200While 1If (getKey(54))E-0.100üEIf (E÷49.000)65.000üEEndJ/*EüF0.000üTPause 200EndIf (getKey(55))E+0.100üEIf (Eù66.000)50.000üEEndJ/*EüF0.000üTPause 200EndgetKey(3)-getKey(2)üAgetKey(1)-getKey(4)üBFnOff X+AüXY+BüYClrDrawPt-On((X/2),(Y/2),8+Pic1)FnOn EndIf getKey(15)LnReg õReturnLbl DGT+KüTIf (TùF)DispGraphõ0.000üTEndReturnLbl DHT+1.000üTIf (TùF)DispGraphõ0.000üTEndReturnLbl DIT+LüTIf (TùF)DispGraphõ0.000üTEndReturnLbl DJT+IüTIf (TùF)DispGraphõ0.000üTEndReturn
Let's run through that code block by block:

Code: [Select]
51.000üE0.000üF108.000üJ0.000üT0üX0üY0üA0üBJ/*EüF0.211üK0.474üI0.740üL
Variable declarations. Notice how almost everything is an 8.8 fixed point number. Why? Because of the way the interrupts will work. (basically, the 108Hz interrupt is the main one, (1 is added to the counter, T, every time it is called), and K, I, and L are the values added to the counter every time a different interrupt is called). K, I, and L are J/value, where value is the Hz for the other interrupts. J is the Interrupt 6 value. Change these to be what is needed for the 83+ models (round to 3 decimal places) using the calculation I just said. F is the target for the counter, and E is the target framerate.

Code: [Select]
[010101010101010101010101]üGDB1[010101010101010101010101][010101010101010101010101][010101010101010101010101][010101010101010101010101][010101010101010101010101][010101010101010101010101][010101010101010101010101][0000000000000000]üPic1[FFFFFFFFFFFFFFFF]
Same old stuff for an RPG (tilemap and sprites)

Code: [Select]
For(Z,0,11)For(Á,0,7)Pt-On((Z*8),(Á*8),(8*{(Á*12)+Z+GDB1})+Pic1)õEndEnd
Drawing the back buffer once (just as an example, put this in a subroutine if you wish)

Code: [Select]
fnInt(DG,0)fnInt(DH,6)fnInt(DI,4)fnInt(DJ,2)
Setting up the interrupts

Code: [Select]
Pause 200While 1If (getKey(54))E-0.100üEIf (E÷49.000)65.000üEEndJ/*EüF0.000üTPause 200EndIf (getKey(55))E+0.100üEIf (Eù66.000)50.000üEEndJ/*EüF0.000üTPause 200EndgetKey(3)-getKey(2)üAgetKey(1)-getKey(4)üBFnOff X+AüXY+BüYClrDrawPt-On((X/2),(Y/2),8+Pic1)FnOn EndIf getKey(15)LnReg õReturn
The main body of the code. There are adjustments using 2nd and mode (1/10 hz adjustments), and the ability to move a block around the screen.

Now for the interrupts:

Code: [Select]
Lbl DGT+KüTIf (TùF)DispGraphõ0.000üTEndReturnLbl DHT+1.000üTIf (TùF)DispGraphõ0.000üTEndReturnLbl DIT+LüTIf (TùF)DispGraphõ0.000üTEndReturnLbl DJT+IüTIf (TùF)DispGraphõ0.000üTEndReturn
Here's what they do: They add their respective values to the counter, and then they see if the counter is greater than or equal to the target counter. If so, the the screen is drawn, and the counter is reset

Long story short: The faster interrupts are fractions of the longer interrupt, and they add to the counter smaller amounts for accuracy. Because there are more times the counter is incremented, the frame rate is more accurate.

I hope this helps! And may the grayscale be with you!
« Last Edit: March 25, 2013, 02:58:07 pm by pimathbrainiac »
I am Bach.

#### Streetwalrus

• LV12 Extreme Poster (Next: 5000)
• Posts: 3821
• Rating: +80/-8
##### Re: [TUTO] How to make "perfect" grayscale in Axe using multiple interrupts!
« Reply #1 on: March 25, 2013, 03:03:58 pm »
You know that they'll be run at random, right ?

#### pimathbrainiac

• Occasionally I make projects
• Members
• LV10 31337 u53r (Next: 2000)
• Posts: 1731
• Rating: +136/-23
• dagaem
##### Re: [TUTO] How to make "perfect" grayscale in Axe using multiple interrupts!
« Reply #2 on: March 25, 2013, 03:07:07 pm »
You know that they'll be run at random, right ?

What do you mean? They'll run the amount of times per second that they should be called.
I am Bach.

#### ralphdspam

• Posts: 841
• Rating: +38/-1
• My name is actually Matt.
##### Re: [TUTO] How to make "perfect" grayscale in Axe using multiple interrupts!
« Reply #3 on: March 25, 2013, 04:43:48 pm »
This is technique is similar to the one I posted in Heylia's thread, but I used an 8.16 counted with the 560Hz interrupt.

I'm not sure is the multiple interrupt routine would work, though.  560, 248, 170, and 118 are all modes of the same hardware interrupt timer.  I don't think you can run then simultaneously.
However, You can ask Runer112 to implement control of the second hardware timer, which runs up to 1120Hz.
« Last Edit: March 25, 2013, 04:46:01 pm by ralphdspam »
ld a, 0
ld a, a

#### Hayleia

• Programming Absol
• Coder Of Tomorrow
• LV12 Extreme Poster (Next: 5000)
• Posts: 3367
• Rating: +393/-7
##### Re: [TUTO] How to make "perfect" grayscale in Axe using multiple interrupts!
« Reply #4 on: March 26, 2013, 11:47:02 am »
Heylia

Also, yeah, I think I once asked if several interrupts could be triggered at once, and I was answered that no, that the best I could do was to put all the routines in one interrupt
Maybe it was changed since, don't know ?
I own: 83+ ; 84+SE ; 76.fr ; CX CAS ; Prizm ; 84+CSE
Sorry if I answer with something that seems unrelated, English is not my primary language and I might not have understood well. Sorry if I make English mistakes too.

#### Streetwalrus

• LV12 Extreme Poster (Next: 5000)
• Posts: 3821
• Rating: +80/-8
##### Re: [TUTO] How to make "perfect" grayscale in Axe using one single interrupt! :P
« Reply #5 on: March 26, 2013, 01:35:46 pm »
Nope, unfortunately the part that allows selecting a routine depending on what triggered the interrupt is broken on the hardware side.
Looking at ASM in 28 days, you'll learn that you can actually have four routines that will be run randomly when an interrupt occurs. Or have 4x the same one, which is done most of the time (and that's prolly what Axe does).

Theoretically, pimath's method is very good, but practically it does not work. Only the DJ routine will be run since it's the last one to be registered, at frequency 2. Which means that it becomes Hayleia method with random garbage added to it. Sorry to break your pride pimath, TI's hardware really sucks.
« Last Edit: March 26, 2013, 01:47:17 pm by Streetwalker »

#### pimathbrainiac

• Occasionally I make projects
• Members
• LV10 31337 u53r (Next: 2000)
• Posts: 1731
• Rating: +136/-23
• dagaem
##### Re: [TUTO] How to make "perfect" grayscale in Axe using multiple interrupts!
« Reply #6 on: March 26, 2013, 02:54:42 pm »
Dangit. I had the theory down, but I didn't know what you just said. Thanks for pointing out my flaws.
I am Bach.