6502 Assembly programming for
the Commodore PET
The PET was the predecessor to the
VIC 20, Released in 1976 it was the earliest of the Commodore home
computers
Later revisions added more memory and a higher screen resolution,
though it was still only 'character based'
|
 |
 |
 |
|
Pet 2001 / 3000 |
Pet 4000 |
SuperPet 9000 |
Cpu |
1mhz 6502 |
1mhz 6502 |
1mhz 6502 + 1mhz 6809 |
Ram |
4/8k + |
8 /16k+ |
96k |
Resolution |
40 x 25 characters
1 characters set |
80 x 25 characters
2 character sets |
80 x 25 Characters
2 character sets |
Colors |
Green / Black |
Green / Black |
Green / Black |
Sound chip |
None / Beeper |
None / Beeper |
None / Beeper |
|

Thanks to "KnightFire66" for the PET photos! |
Useful Documents
PetFaq
Quick
Reference
The Pet Revealed
ChibiAkumas Tutorials
6502
Lesson H10 - Hello World on the Commodore PET
Lesson P38
- Character Block Graphics on the Pet
Lesson P39
- Key reading on the PET
Lesson P40
- Sound on the PET
Lesson S19 -
Kepad Reading on the Commodore PET!
Lesson
S32 - Char Block clipping on the Commodore PET!
Lesson P49
- Sound on the Commodore PET (ChibiSound Pro)
Memory Map
From |
To |
Function |
$0000 |
$3FF |
OS and Basic
storage |
$0400 |
$1FFF |
Basic Program
/ 8k main ram |
$2000 |
$7FFF |
32k extension |
$8000 |
$83FF |
VRAM |
$C000 |
$E7FF |
Basic ROM |
$E800 |
$EFFF |
I/O |
$F000
|
$FFFF
|
OS ROM |
Interrupt vectors
The standard 6502 interrupt vectors from $FFFA+ are ROM, however these
jump to vectors in low memory addresses. IRQ and BRK interrupts push A,X
and Y onto the stack in that order.
VBLank interrupts cause a CB1 IRQ interrupt. This can be disabled with
"lda #%11111100 sta $e813"
Note: The vector addresses were different on the first generation 2001-8
machine.
2001-8 |
Others |
|
|
From |
To |
From |
To |
Function |
Registers
Pushed |
$0219
|
$021A |
$0090 |
$0091 |
IRQ |
A X Y |
$021B |
$021C |
$0092 |
$0093 |
BRK |
A X Y |
None |
None |
$0094 |
#0095 |
NMI |
|
Character Map
Write #12 to $E84C

|
Write #14 to $E84C

|
Keymap
Rom Functions
Address |
Purpose |
$FFD2 |
PrintChar A |
$FFE4 |
ReadChar A |
$FFCF |
Input a character |

I/O Map
Port |
Purpose |
Bits |
Notes |
$E810 |
PIA1:Key Row
select (0-9) |
DICcKKKK |
D=Diagnostic
sense / I=IEEE EOI in / C=Cassette sense #2 / c==Cassette sense #1
/ K=Keyboard Row select |
$E811 |
PIA1:Screen /
Tape |
T-SSSDCC |
T=Tape #1
input flag / S = Screen blank (old 8k only) IEE EOI Out CA2 /
D=DDRA Access / C=Casette #1 read control CA1 |
$E812 |
PIA1:Key Data |
KKKKKKKK |
K=Keyboard
Row Input |
$E813 |
PIA1:Screen /
Tape |
R-CCCDrr |
R=Retrace I
flag / C=Cassette #1 Motor output CB2 / D=DDRB Access / r= retrace
interrupt control CB1 |
$E820 |
PIA2:IEEE488
Input |
IIIIIIII |
I=IEEE Input |
$E821 |
PIA2:IEEE488 |
A-INCDia |
A=ATN I Flag
/ I=IEEE/ N=Ndac Out/ C=CA2 / D=DDRA Access / i=IEEE control /
a=ATN in CA1 |
$E822 |
PIA2:IEEE488
Output |
OOOOOOOO |
O=IEEE Output |
$E823 |
PIA2:IEEE488 |
S-IDCdis |
S=SRQ I Flag
/ I=IEEE / D=DAV out / C=CB2 / d=DDRB access / i=IEEE control /
s=SRQ in CB1 |
$E840 |
VIA:IO Port B
output |
DNRCOAnd |
D=Dav in /
N=NFRD In / R=Retrace In / C=Cassette #2 motor / O=Cassette output
/ O=Atn Out / n=NFRD out / d=NDAC in PB |
$E841 |
VIA:IO Port A
output |
|
|
$E842 |
VIA:IO Port B
direction (1=out 0=in) |
BBBBBBBB |
Data
Direction register B (For E840) |
$E843 |
VIA:IO Port A
direction |
AAAAAAAA |
Data
Direction register A (For E84F) |
$E844 |
VIA:Timer 1 L |
LLLLLLLL |
|
$E845 |
VIA:Timer 1 H |
HHHHHHHH |
|
$E846 |
VIA:Timer 1
Latch L |
LLLLLLLL |
|
$E847 |
VIA:Timer 1
Latch H |
HHHHHHHH |
|
$E848 |
VIA:Timer 2 L |
LLLLLLLL |
64-255 =
Sound Frequency |
$E849 |
VIA:Timer 2 H |
HHHHHHHH |
|
$E84A |
VIA:Shift
Register |
SSSSSSSS |
15/51/85 =
Sound Octive |
$E84B |
VIA:Aux
Control Register |
1O2SSSPP |
1=T1 Control
PB7 Out / O=One shot free run / 2=T2 control PB6 sense / S=Shift
register control / P=PB PA Latch control ... (16= Sound On) |
$E84C |
VIA:Peripheral
control |
BBBbAAAa |
B=CB2 (Pup)
control in/out / b=CB1 in casette #2 / A= CA2 graphics lowecase in
out / a=CA1 in polarity .... 12=Graphics |
$E84D |
VIA:Interrupt
Flag Register (IFR) |
ITtBBSAa |
I=IRQ status
/ T=T1 interrupt / t=T2 interrupt / B=CB1 Casette / S=SR Interrupt
/ A=CA1 Interrupt / a=CA2 Interrupt |
$E84E |
VIA:Interrupt
enable register |
ETtBbSAa |
E=Enable or
disable following ints / T=T1 interrupt / t=T2 interrupt / B=CB1
interrupt / b=CB2 Interrupt / S=SR interrupt / A=CA1 Interrupt /
a=CA2 interrupt |
$E84F |
VIA:IO Port A
Output without handshaking |
AAAAAAAA |
Paralell user
port I/O - Port A |
$E856 |
CRTC:Reg
select |
RRRRRRRR |
|
$E857 |
CRTC:Reg Data |
DDDDDDDD |
|
$FFF0 |
64k Expansion
Control Register |
EIS-BbWw |
E=Enable I=IO
Ram $E800-EFFF S=Scrn Ram $8000-$8FFF B=bank 1/3 $C000-$FFFF
b=bank 0/2 $8000-$BFFF W=Write protect 1/3 w=Write protect 0/2 |
Sound
The PET did not have any built in sound, but a speaker can be connected
to the IO port.
The PET is capable of up to 4 octaves... one of 3 possible pairs can be
selected with $E84A
Address $E84B will turn the sound on or off... we
write #16 to turn it on, #0 to turn it off.
Address $E84A can be used to select the Octave with
value 15/51/85
Address $E848 can be used to select the note, a
value of 64-255 should be passed.
It is not possible to set the volume, or play multiple tones at the same
time.
Note Freq |
octave=15 |
octave=51 |
octave=85 |
Octave 0 |
Octave 1 |
Octave 1 |
Octave 2 |
Octave 2 |
Octave 3 |
B |
251 |
125 |
251 |
125 |
251 |
125 |
C |
238 |
118 |
238 |
118 |
238 |
118 |
C# |
224 |
110 |
224 |
110 |
224 |
110 |
D |
210 |
104 |
210 |
104 |
210 |
104 |
D# |
199 |
99 |
199 |
99 |
199 |
99 |
E |
188 |
93 |
188 |
93 |
188 |
93 |
F |
177 |
88 |
177 |
88 |
177 |
88 |
F# |
168 |
83 |
168 |
83 |
168 |
83 |
G |
158 |
78 |
158 |
78 |
158 |
78 |
G# |
149 |
74 |
149 |
74 |
149 |
74 |
A |
140 |
69 |
140 |
69 |
140 |
69 |
A# |
133 |
65 |
133 |
65 |
133 |
65 |
(Sound info taken from the PetFaq)
|