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 |
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
Lesson
H10 - Hello World on the Commodore PET
Lesson
S32 - Char Block clipping on the Commodore PET!
Lesson S19 -
Keypad Reading 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
P49 - Sound on the Commodore PET (ChibiSound Pro)
Lesson
P63 - Multiplatform Software tilemap on the PET
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.
Immediately after the pushes, the interrupt handler at the addresses
below are executed.
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 (Data Direction Reg A) / 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 (Data
Direction Reg B) / r= retrace interrupt control CB1 (rr=1
Vblank interrupt)
|
$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)
|