CHIP-8 TUTORIAL

This section is intended to provide an introduction to CHIP-8 programming, as it applies to the CHIP-8 Classic computer.

The lessons are in the format of commonly asked questions.

On your computer - your program is placed in memory by entering the EDIT mode of operation.

This is accomplished by pressing the F1 key, followed by the 0 key.

To exit EDIT mode, and return to the Monitor
(COMMAND mode) simply press the F2 key.

Programs are run by pressing the F1 key, followed by the 3 key.​

Press this Button at any time to reference the Instruction Set:

CHIP-8 Instruction Set

How do I clear the Display?​​​​

Use the 00E0 instruction.

This makes a GREAT first program!

You may have noticed - When the CHIP-8 computer is first turned on, the Screen contains random data.
Prior to writing your own programs that utilize the display, you will want to clear the screen of any rubbish that doesn't need to be there.

Heres how it's done:​

From COMMAND mode, enter 0200 on the keypad.


Enter EDIT mode.


Enter data 00E0.


You will see on the display that the address has auto incremented to 0202H.


Enter data F000.


Press the F2 key, to return to COMMAND mode.


Press the F1 key, followed by the 3 key to run the code.

CONGRATULATIONS! You just ran your first CHIP-8 program...


The program code for what you just did is shown in this format:


0200:      00E0        Clear the Screen.
                F000        Return to Monitor.


The 2nd line of the code, returns the processor back to the Monitor.


This is an important step because it gives you the ability to execute further Monitor commands.

How do I write a character to the Screen?​​​​​

​​​
CHIP-8 display characters are called Sprites. ​​
Prior to writing a Sprite to the screen - The CHIP-8 Interpreter first looks to see what Sprite is already at the pointed to Screen co-ordinates.
It then XOR's this data with the new data, and places the result on the display. 

Because of this, rewriting a Sprite to the same location also erases the Sprite. This is useful for Game animation.

The CHIP-8 display has a resolution of 64 by 32 pixels.

The screens origin is at the top left corner, at screen XY co-ordinates (0,0).

X co-ordinates range from 0 to 3FH, and Y co-ordinates range from 0 to 1FH.

The following code outlines the Sprite drawing process, where a Sprite (X) is drawn at Screen co-ordinates 0,0:

0200:       00E0       Clear the Screen.
                 6000       Set X co-ordinate.
                 6100       Set Y co-ordinate.
                 A300       Set Sprite location.
                 D015       Draw Sprite.
                 F000        Return to Monitor.

​0300:       2112
                 0C12
                 2100

To draw the Sprite at a different Screen location - change registers V0, and V1.
For example, changing V0 to 01H moves the Sprite one pixel to the right.

The Sprites pattern is located at address 0300H. In this case - 5 bytes of data.

The DXYN instruction can write up to 15 bytes at a time. Therefore, the Sprite could be 8 pixels by 15 pixels.

Larger Sprites can be created by executing the DXYN instruction multiple times.

How do I write a Hexadecimal number to the Screen?


Use the FX29 Instruction.​​​

The CHIP-8 Interpreter has in-built Fonts for the Hexadecimal numbers 0 through F. Font size is 4 by 5 pixels.

Simply place the hex value in a register (V0-VF), and reference that register using the FX29 instruction prior to drawing the Sprite.

Here is a program example:

0200:      00E0      Clear the Screen.
                6000      Set X co-ordinate.
                6100      Set y co-ordinate.
                620A      Put number in V2.
                F229      Point to the A font.
                D015     Draw Sprite.
                F000      Return to Monitor. 

​A different number can be written to the screen by changing the contents of V2.

How do I read a character from the Keypad?

​​​​​​​​​​​​​
Use the FX0A instruction; where X is an 8 Bit register (V0 to VF).

Once this instruction is encountered, the processor will stop further instruction execution until a key is pressed on the keypad.

The keycode will be placed into the specified register.

Valid keycodes are:

0 - 00H, 1 - 01H, 2 - 02H, 3 - 03H
4 - 04H, 5 - 05H, 6 - 06H, 7 - 07H
8 - 08H, 9 - 09H, A - 0AH, B- 0BH
C- 0CH, D- 0DH,  E - 0EH, F - 0FH

​Here is a program example:

0200:      F00A          Wait for a keypress.
                3008          Skip if V0=08H.
                F000          Return to Monitor.
                1300          Continue.

This code waits for a keypress, and executes further code at 0300H - but only if the key is an 8.

How do I add two numbers together?


Use the 8XY4 instruction; where VX=VX+VY.​​​​​​​​​​​​​​​​​​

VX and VY can be any two registers - Select from V0 to VF.
Lets choose V0 for X, and V1 for Y.
From this the instruction becomes 8014.


Lets put 20 Hex (32 decimal) in V0, and 12 Hex (18 decimal) in V1.


The program becomes:


0200:       6020           Load V0 with 20H.
                 6112           Load V1 with 12H.
                 8014           Add V0 to V1.


After running these 3 lines of code, V0 will contain 32 Hex (50 decimal).


How do I create a delay loop?


A delay loop can be achieved in 4 lines of code:


0200:         6400          Clear V4.
0202:         7401           Inc V4.
0204:         34FF           Skip if V4=FFH.
0206:         1202           Jump to 0202H.


When the program completes, it falls through to line 5 (Address 0208H).

Apart from killing time in a program, this is also a useful routine for repeating an action (multiple times).

In this example you would add the code for what you want to accomplish at address 0202H, and the rest of the delay code simply moves down a line.

How do I increase the delay time?


A much larger delay can be created by embedding an FF delay loop within another loop.


If the delay loop is terminated with a return instruction (00EE) it can be placed at a high address, and used as a subroutine.


Here is an example:

0200:        2500          Call to 0500H.


0500:        6600          Clear V6.
0502:        7601          Inc V6.
0504:        6500          Clear V5.
0506:        7501          Inc V5.
                  35FF          Skip if V5=FF.
                  1506          Jump to 0506H.
                  36A0         Skip if V6=A0.
                  1502          Jump to 0502H.
                   00EE         Return to 0200H.


How do I send a byte of data out the RS-485 port?

First of all you set up the Baud rate, then transmit the data.​​​​​​

All tranmissions will be 8 data bits, no parity, 1 stop bit.

Here is a program example:

0200:      6009
                F072           Set Baud rate to 115,200.
                6031
                F070           Send the ASCII character (1).

                


How do I receive RS-485 data?

Use the FX71 command.

When the processor encounters this command it will wait until a byte of data is received on the RS-485 port.
The data is placed in the specified register.

Here is a program example:

0200:       F071               Wait for RS-485 data.
                 3031               Skip if its the ASCII character (1).
                 F000               Return to the Monitor.
                 1300               Jump to the Receive data routine.

Is there an easy way of decrementing a Register?

Use the 7XKK Instruction, to add FFH to the number.

Here is an example:

0200:         6A29            Load VA with 29H.
                   7AFF            Add FFH to VA.

After running this code, VA=28H.

How do I animate a Sprite?​​

Sprite animation is performed by capitalizing on Persistance of Vision.​

Firstly, draw a Sprite to a screen co-ordinate. Now - erase the Sprite.
Move the Sprite to an adjacent Screen co-ordinate,  and perform the same actions.
Its also helpful to call a delay after drawing, as the routine happens very quickly.

This code demonstrates the process:

0200:          00E0             Clear the Screen.
                    6A00             Set the X co-ordinate to 00H.
                    6B00             Set the Y co-ordinate to 00H.
                    2400             Draw SPRITE A.
                    2500             Keep on the Screen for a moment.
                    2400             Erase the Sprite. (XOR with the previously drawn Sprite).
                    2500             Call delay.
                    7A01             Increment X to the next Screen position.
                    2600             Draw SPRITE B.
                    2500             Keep on the Screen for a moment.
                    2600             Erase the Sprite.
                    2500             Call delay.
                    7A01             Increment X.
                    1206             Keep animating the Sprite.

0300:           BA7C            Sprite A data.
                     D6FE
                     54AA

0310:           7C7C             Sprite B data.
                     D6FE
                     546C

0400:           A300             Sprite A Address.
                     DAB6            Draw Sprite A.
                     00EE             Return.

​0500:           6600             Delay Routine - clear V6.
0502:           7601             Increment V6 - Outer delay loop.
                     6500             Clear V5.
0506:           7501             Increment V5 - Inner delay loop.
                     3508             Skip if V5=08H.
                     1506             Jump to 0506H.
                     36A0            Skip if V6=A0H.
                     1502             Jump to 0502H. 
                     00EE             Return.

0600:           A310             Sprite B Address.
                     DAB6            Draw Sprite B.
                     00EE             Return. 

     

How do I check my Firmware Revision?

From COMMAND mode, enter 0040 on the keypad. This is the start address that holds the Firmware Revision data (2 Bytes).

Enter EDIT mode.


Write down the data.

Press the F1 key to increment the address to 0041H.

Write down the data.

Press the F2 key to return to Command mode.

If, for example - the two bytes are 02H and 61H. This would correspond to FW Revision 2.61.