9.3. I/O Units

I/O Units are interfaces between Apple memory and the peripherals. In the emulator, it is an interface between core layer and hardware layer.

9.3.1. Unit class

I/O Units are represented by child classes of the CUnit class.

On the Apple memory side, only two methods are used : read and write. This is much like Memory, except that the addressing is on 8 bits rather than 16.

On the peripheral side, there is no specification. Most units only consist of soft switches. To each switch corresponds a get_<switch> method and, if changeable, a set_<switch> method, where <switch> is the switch name in lowercase.

Units have a reset method which is supposed to reset the unit. It is called both at the unit instantiation and when the user presses the reset button (this is in the hardware layer).

All units are observable and should notify whenever any change occurs. Hardware layer objects should observe units to be informed of what's happening.

9.3.2. Keyboard

Compatibility: All models.

This unit is in charge of keyboard. On Apple II computer there was no keyboard buffer. This unit can only handle one key at once.

9.3.2.1. Methods

void press_key(BYTE key);

Tells the unit that key is being pressed. Note that if the previous key has not been read yet, it will be forgotten. The key code must be an Apple ASCII code.

void release_key();

Tells the unit that the pressed key has been released.

bool key_waiting();

Tells if there's a key waiting to be read by the Apple. This method could be very convenient for developing a buffered keyboard or a copy paste tool.

9.3.2.2. Addresses

AddressNameAccessEffect
0x00KBDRBits 0-6 : Last key pressed or being pressed. Bit 7 : is set if a key has been pressed since last strobe.
0x10KBDSTROBERWStrobes the keyboard. Bits 0-6 : Last key pressed or being pressed. Bit 7 : is set if the key is being pressed.

9.3.3. Tape

Compatibility: All models.

Unfortunately this unit is not yet implemented.

9.3.4. Speaker

Compatibility: All models.

The Apple speaker is quite basic : it has only two levels. Speaker level is toggled by accessing to the SPKR soft switch. On the peripheral side, the current speaker level can be read.

9.3.4.1. Switches

SwitchOffOn
SPKRSpeaker at low levelSpeaker at high level

9.3.4.2. Addresses

AddressNameAccessEffect
0x30SPKRRWToggle SPKR switch

9.3.5. Game

Compatibility: All models (maybe except //c).

Game unit has three different kinds of devices : Three push buttons, four annunciators and four analog inputs.

Push buttons are connected to the joystick or paddles buttons. Button 0 is also connected to the open apple keyboard key and button 1 to the closed apple key. On a few //e models, the button 2 is connected to the shift key.

Annunciators are outputs on the game plug, capable of outputting an two levels signal (they have not been used so much, maybe not at all).

Analogs inputs are connected to the joystick X and Y axis (usually inputs 0 and 1) or to the paddles. These analog inputs worked by measuring the discharge time of a capacitor into variable resistance of paddle or joystick. The unit was only able to trigger the capacitor load and sense when it was discharged. The time is measured by a program in ROM.

It is important to simulate this mechanism as some software implements their own measuring routine. The difficulty is that it is important to synchronize the simulator to the clock so the cycle count, seen from the inside, is correct.

9.3.5.1. Switches

SwitchOffOn
AN0Annunciator 0 level is lowAnnunciator 0 level is high
AN1Annunciator 1 level is lowAnnunciator 1 level is high
AN2Annunciator 2 level is lowAnnunciator 2 level is high
AN3Annunciator 3 level is lowAnnunciator 3 level is high
PB0Push button 0 is releasedPush button 0 is pressed
PB1Push button 1 is releasedPush button 1 is pressed
PB2Push button 2 is releasedPush button 2 is pressed
PADDL0Paddle 0 capacitor is emptyPaddle 0 capacitor is loaded
PADDL1Paddle 1 capacitor is emptyPaddle 1 capacitor is loaded
PADDL2Paddle 2 capacitor is emptyPaddle 2 capacitor is loaded
PADDL3Paddle 3 capacitor is emptyPaddle 3 capacitor is loaded
PTRIGPaddle capacitors are dischargingPaddle capacitors are loading

9.3.5.2. Addresses

AddressNameAccessEffect
0x58CLRAN0WRTurn AN0 switch off
0x59SETAN0WRTurn AN0 switch on
0x5ACLRAN1WRTurn AN1 switch off
0x5BSETAN1WRTurn AN1 switch on
0x5CCLRAN2WRTurn AN2 switch off
0x5DSETAN2WRTurn AN2 switch on
0x5ECLRAN3WRTurn AN3 switch off
0x5FSETAN3WRTurn AN3 switch on
0x61PB0R7Read PB0 switch state
0x62PB1R7Read PB1 switch state
0x63PB2R7Read PB2 switch state
0x64PADDL0R7Read PADDL0 switch state
0x65PADDL1R7Read PADDL1 switch state
0x66PADDL2R7Read PADDL2 switch state
0x67PADDL3R7Read PADDL3 switch state
0x70PTRIGRTrigger capacitor discharges*

* : When the capacitor charge is triggered, the PTRIG switch goes true, observers are notified, then it goes back false (and observers are notified again). All that in the same clock cycle (actually during the same method call). This is the way the Game unit informs observers that they should begin discharge simulation.

9.3.6. Graphic Mode

Compatibility: All models.

Reference: Apple IIe Technical Reference Manual page 29 (PDF p63)

This unit takes care of graphic and text modes switching, except the double hires mode which was implemented later. The Apple ][ has one text mode and two graphic modes (low resolution and high resolution). A mixed mode allows to split the screen having 4 lines of text at the bottom and the rest in graphic mode. Each mode has two pages corresponding to different memory spaces.

9.3.6.1. Switches

SwitchOffOn
TEXTGraphic ModeText mode
MIXEDFull screen modeSplit screen mode
PAGE2Page 1 displayedPage 2 displayed
HIRESLow resolution High resolution

9.3.6.2. Addresses

AddressNameAccessEffect
0x50TXTCLRRWTurn TEXT switch off
0x51TXTSETRWTurn TEXT switch on
0x52MIXCLRRWTurn MIXED switch off
0x53MIXSETRWTurn MIXED switch on
0x54TXTPAGE1RWTurn PAGE2 switch off
0x55TXTPAGE2RWTurn PAGE2 switch on
0x56LORESRWTurn HIRES switch off
0x57HIRESRWTurn HIRES switch on

And, on //e and later, some read addresses were added :

AddressNameAccessEffect
0x1ARDTEXTR7Read TEXT switch state
0x1BRDMIXEDR7Read MIXED switch state
0x1CRDPAGE2R7Read PAGE2 switch state
0x1DRDHIRESR7Read HIRES switch state

9.3.7. Slots

Compatibility: All models.

This units manages the expansion slots of the Apple. It just forwards read and write requests on the $C090-$C0FF memory space to the corresponding card's I/O unit.

Like Slot ROM Bus, this unit has to be informed when a card is inserted or removed.

9.3.7.1. Methods

void insert_card(int slot, CUnit *cardUnit);

Tells the unit that a card has been inserted. slot is the slot number (1-7) and cardUnit is the I/O unit of the expansion card.

void remove_card(int slot);

Tells the unit that a card has been removed. slot is the slot number (1-7).

9.3.7.2. Addresses

AddressNameAccessEffect
0x90-0x9F RWForwarded to addresses 0x00-0x0F of card in slot 1
0xA0-0xAF RWForwarded to addresses 0x00-0x0F of card in slot 2
0xB0-0xBF RWForwarded to addresses 0x00-0x0F of card in slot 3
0xC0-0xCF RWForwarded to addresses 0x00-0x0F of card in slot 4
0xD0-0xDF RWForwarded to addresses 0x00-0x0F of card in slot 5
0xE0-0xEF RWForwarded to addresses 0x00-0x0F of card in slot 6
0xF0-0xFF RWForwarded to addresses 0x00-0x0F of card in slot 7

9.3.8. Language Card

Compatibility: All models (probably not ][).

Reference : Apple IIe Technical Reference Manual pages 79 to 83 (PDF pp113-117)

This unit drives the Language Card Bus using three switches : LCRAM, LCBNK2 and LCWRITE.

Only LCRAM and LCBNK2 are visible from inside the Apple. LCWRITE is not an official name for this switch (I chose this one because I did not found any name in documentation).

To change state of LCWRITE, two read requests must be done on the appropriate address. A fourth switch is used in Vinace to manage that double read and is called LCWCHG.

9.3.8.1. Switches

SwitchOffOn
LCBNK2RAM bank 2 is used in $D000-$DFFFRam bank 1 is used in $D000-$DFFF
LCRAMROM is read in $D000-$FFFFRAM is read in $D000-$DFFF
LCWRITENo write operation in $D000-$FFFFRAM is writable in $D000-$FFFF (even if not visible)

9.3.8.2. Addresses

AddressNameAccessEffect
0x11RDLCBNK2R7Read LCBNK2 switch state
0x12RDLCRAMR7Read LCRAM switch state
0x81 RTurn LCBNK2 on, LCRAM on, LCWRITE off
0x81 RRTurn LCBNK2 on, LCRAM off, LCWRITE on
0x82 RTurn LCBNK2 on, LCRAM off, LCWRITE off
0x83 RRTurn LCBNK2 on, LCRAM on, LCWRITE on
0x84-0x87  Same as 0x80-0x83
0x88 RTurn LCBNK2 off, LCRAM on, LCWRITE off
0x89 RRTurn LCBNK2 off, LCRAM off, LCWRITE on
0x8A RTurn LCBNK2 off, LCRAM off, LCWRITE off
0x8B RRTurn LCBNK2 off, LCRAM on, LCWRITE on
0x8C-0x8F  Same as 0x88-0x8B

9.3.9. Aux Memory

Compatibility: //e and later.

Unfortunately this unit is not yet implemented.

9.3.10. Text Mode

Compatibility: //e and later.

This unit takes care of 40/80 columns display switching and charset switching.

9.3.10.1. Switches

SwitchOffOn
80VID40 columns display80 columns display
ALTCHARPrimary charset usedAlternative charset used

9.3.10.2. Addresses

AddressNameAccessEffect
0x0CCLR80VIDWTurn 80VID switch off
0x0DSET80VIDWTurn 80VID switch on
0x0ECLRALTCHARWTurn ALTCHAR switch off
0x0FSETALTCHARWTurn ALTCHAR switch on
0x1ERDALTCHARR7Read ALTCHAR switch state
0x1FRD80VIDR7Read 80VID switch state

9.3.11. I/O Rom

Compatibility : //e, IIgs

Some Apple models had more than 12k of ROM. To access the rest of the ROM, the space $C100-$CFFF, usually reserved for peripheral ROM could be used. A window in $C300-$C3FF, corresponding to the 80 column card, can be specifically selected.

This unit drives the I/O Rom bus that takes care of $C100-$CFFF ROM switching between slot ROM and internal ROM.

9.3.11.1. Switches

SwitchOffOn
CXROMPeripheral ROM at $C100-$CFFFInternal ROM at $C100-$CFFF
C3ROMROM selected by CXROM at $C300-$C3FFInternal ROM at $C300-$C3FF

9.3.11.2. Addresses

AddressNameAccessEffect
0x06SETSLOTCXROMWTurn CXROM switch off
0x07SETINTCXROMWTurn CXROM switch on
0x0ASETINTC3ROMWTurn C3ROM switch off
0x0BSETSLOTC3ROMWTurn C3ROM switch on
0x15RDCXROMR7Read CXROM switch state
0x17RDC3ROMR7Read C3ROM switch state