diff --git a/ASM/basic_ops.asm b/ASM/basic_ops.asm new file mode 100644 index 0000000..436df26 --- /dev/null +++ b/ASM/basic_ops.asm @@ -0,0 +1,16 @@ + + ; TEST ADDRESSING MODES + ; $FFFC and $FFFD - RESET PROGRAM COUNTER + + processor 6502 + + org $FF00 + + lda #$00 + sta $0000 +loop + lda $0000 + tax + inx + stx $0000 + jmp loop diff --git a/ASM/read_write.asm b/ASM/read_write.asm new file mode 100644 index 0000000..2df48c8 --- /dev/null +++ b/ASM/read_write.asm @@ -0,0 +1,15 @@ + + ; TEST ADDRESSING MODES + ; $FFFC and $FFFD - RESET PROGRAM COUNTER + + processor 6502 + + org $FF00 + +loop + lda #$AA + sta $0000 + lda #$BB + sta $0001 + nop + jmp loop diff --git a/ASM/readonly_loop.asm b/ASM/readonly_loop.asm new file mode 100644 index 0000000..7fdc0ff --- /dev/null +++ b/ASM/readonly_loop.asm @@ -0,0 +1,14 @@ + + ; TEST ADDRESSING MODES + ; $FFFC and $FFFD - RESET PROGRAM COUNTER + + processor 6502 + + org $FF00 + +loop + nop + nop +loop2 + nop + jmp loop2 diff --git a/ASM/woz_monitor.asm b/ASM/woz_monitor.asm new file mode 100644 index 0000000..8189ed0 --- /dev/null +++ b/ASM/woz_monitor.asm @@ -0,0 +1,259 @@ +;------------------------------------------------------------------------- +; +; The WOZ Monitor for the Apple 1 +; Written by Steve Wozniak 1976 +; +;------------------------------------------------------------------------- + + .CR 6502 + .OR $FF00 + .TF WOZMON.HEX,HEX,8 + +;------------------------------------------------------------------------- +; Memory declaration +;------------------------------------------------------------------------- + +XAML .EQ $24 Last "opened" location Low +XAMH .EQ $25 Last "opened" location High +STL .EQ $26 Store address Low +STH .EQ $27 Store address High +L .EQ $28 Hex value parsing Low +H .EQ $29 Hex value parsing High +YSAV .EQ $2A Used to see if hex value is given +MODE .EQ $2B $00=XAM, $7F=STOR, $AE=BLOCK XAM + +IN .EQ $0200,$027F Input buffer + +KBD .EQ $D010 PIA.A keyboard input +KBDCR .EQ $D011 PIA.A keyboard control register +DSP .EQ $D012 PIA.B display output register +DSPCR .EQ $D013 PIA.B display control register + +; KBD b7..b0 are inputs, b6..b0 is ASCII input, b7 is constant high +; Programmed to respond to low to high KBD strobe +; DSP b6..b0 are outputs, b7 is input +; CB2 goes low when data is written, returns high when CB1 goes high +; Interrupts are enabled, though not used. KBD can be jumpered to IRQ, +; whereas DSP can be jumpered to NMI. + +;------------------------------------------------------------------------- +; Constants +;------------------------------------------------------------------------- + +BS .EQ $DF Backspace key, arrow left key +CR .EQ $8D Carriage Return +ESC .EQ $9B ESC key +PROMPT .EQ "\" Prompt character + +;------------------------------------------------------------------------- +; Let's get started +; +; Remark the RESET routine is only to be entered by asserting the RESET +; line of the system. This ensures that the data direction registers +; are selected. +;------------------------------------------------------------------------- + +RESET CLD Clear decimal arithmetic mode + CLI + LDY #%0111.1111 Mask for DSP data direction reg + STY DSP (DDR mode is assumed after reset) + LDA #%1010.0111 KBD and DSP control register mask + STA KBDCR Enable interrupts, set CA1, CB1 for + STA DSPCR positive edge sense/output mode. + +; Program falls through to the GETLINE routine to save some program bytes +; Please note that Y still holds $7F, which will cause an automatic Escape + +;------------------------------------------------------------------------- +; The GETLINE process +;------------------------------------------------------------------------- + +NOTCR CMP #BS Backspace key? + BEQ BACKSPACE Yes + CMP #ESC ESC? + BEQ ESCAPE Yes + INY Advance text index + BPL NEXTCHAR Auto ESC if line longer than 127 + +ESCAPE LDA #PROMPT Print prompt character + JSR ECHO Output it. + +GETLINE LDA #CR Send CR + JSR ECHO + + LDY #0+1 Start a new input line +BACKSPACE DEY Backup text index + BMI GETLINE Oops, line's empty, reinitialize + +NEXTCHAR LDA KBDCR Wait for key press + BPL NEXTCHAR No key yet! + LDA KBD Load character. B7 should be '1' + STA IN,Y Add to text buffer + JSR ECHO Display character + CMP #CR + BNE NOTCR It's not CR! + +; Line received, now let's parse it + + LDY #-1 Reset text index + LDA #0 Default mode is XAM + TAX X=0 + +SETSTOR ASL Leaves $7B if setting STOR mode + +SETMODE STA MODE Set mode flags + +BLSKIP INY Advance text index + +NEXTITEM LDA IN,Y Get character + CMP #CR + BEQ GETLINE We're done if it's CR! + CMP #"." + BCC BLSKIP Ignore everything below "."! + BEQ SETMODE Set BLOCK XAM mode ("." = $AE) + CMP #":" + BEQ SETSTOR Set STOR mode! $BA will become $7B + CMP #"R" + BEQ RUN Run the program! Forget the rest + STX L Clear input value (X=0) + STX H + STY YSAV Save Y for comparison + +; Here we're trying to parse a new hex value + +NEXTHEX LDA IN,Y Get character for hex test + EOR #$B0 Map digits to 0-9 + CMP #9+1 Is it a decimal digit? + BCC DIG Yes! + ADC #$88 Map letter "A"-"F" to $FA-FF + CMP #$FA Hex letter? + BCC NOTHEX No! Character not hex + +DIG ASL + ASL Hex digit to MSD of A + ASL + ASL + + LDX #4 Shift count +HEXSHIFT ASL Hex digit left, MSB to carry + ROL L Rotate into LSD + ROL H Rotate into MSD's + DEX Done 4 shifts? + BNE HEXSHIFT No, loop + INY Advance text index + BNE NEXTHEX Always taken + +NOTHEX CPY YSAV Was at least 1 hex digit given? + BEQ ESCAPE No! Ignore all, start from scratch + + BIT MODE Test MODE byte + BVC NOTSTOR B6=0 is STOR, 1 is XAM or BLOCK XAM + +; STOR mode, save LSD of new hex byte + + LDA L LSD's of hex data + STA (STL,X) Store current 'store index'(X=0) + INC STL Increment store index. + BNE NEXTITEM No carry! + INC STH Add carry to 'store index' high +TONEXTITEM JMP NEXTITEM Get next command item. + +;------------------------------------------------------------------------- +; RUN user's program from last opened location +;------------------------------------------------------------------------- + +RUN JMP (XAML) Run user's program + +;------------------------------------------------------------------------- +; We're not in Store mode +;------------------------------------------------------------------------- + +NOTSTOR BMI XAMNEXT B7 = 0 for XAM, 1 for BLOCK XAM + +; We're in XAM mode now + + LDX #2 Copy 2 bytes +SETADR LDA L-1,X Copy hex data to + STA STL-1,X 'store index' + STA XAML-1,X and to 'XAM index' + DEX Next of 2 bytes + BNE SETADR Loop unless X = 0 + +; Print address and data from this address, fall through next BNE. + +NXTPRNT BNE PRDATA NE means no address to print + LDA #CR Print CR first + JSR ECHO + LDA XAMH Output high-order byte of address + JSR PRBYTE + LDA XAML Output low-order byte of address + JSR PRBYTE + LDA #":" Print colon + JSR ECHO + +PRDATA LDA #" " Print space + JSR ECHO + LDA (XAML,X) Get data from address (X=0) + JSR PRBYTE Output it in hex format +XAMNEXT STX MODE 0 -> MODE (XAM mode). + LDA XAML See if there's more to print + CMP L + LDA XAMH + SBC H + BCS TONEXTITEM Not less! No more data to output + + INC XAML Increment 'examine index' + BNE MOD8CHK No carry! + INC XAMH + +MOD8CHK LDA XAML If address MOD 8 = 0 start new line + AND #%0000.0111 + BPL NXTPRNT Always taken. + +;------------------------------------------------------------------------- +; Subroutine to print a byte in A in hex form (destructive) +;------------------------------------------------------------------------- + +PRBYTE PHA Save A for LSD + LSR + LSR + LSR MSD to LSD position + LSR + JSR PRHEX Output hex digit + PLA Restore A + +; Fall through to print hex routine + +;------------------------------------------------------------------------- +; Subroutine to print a hexadecimal digit +;------------------------------------------------------------------------- + +PRHEX AND #%0000.1111 Mask LSD for hex print + ORA #"0" Add "0" + CMP #"9"+1 Is it a decimal digit? + BCC ECHO Yes! output it + ADC #6 Add offset for letter A-F + +; Fall through to print routine + +;------------------------------------------------------------------------- +; Subroutine to print a character to the terminal +;------------------------------------------------------------------------- + +ECHO BIT DSP DA bit (B7) cleared yet? + BMI ECHO No! Wait for display ready + STA DSP Output character. Sets DA + RTS + +;------------------------------------------------------------------------- +; Vector area +;------------------------------------------------------------------------- + + .DA $0000 Unused, what a pity +NMI_VEC .DA $0F00 NMI vector +RESET_VEC .DA RESET RESET vector +IRQ_VEC .DA $0000 IRQ vector + +;------------------------------------------------------------------------- + + .LI OFF diff --git a/ASM/woz_monitor_dasm.asm b/ASM/woz_monitor_dasm.asm new file mode 100644 index 0000000..9a9d8ba --- /dev/null +++ b/ASM/woz_monitor_dasm.asm @@ -0,0 +1,258 @@ +;------------------------------------------------------------------------- +; +; The WOZ Monitor for the Apple 1 +; Written by Steve Wozniak 1976 +; +;------------------------------------------------------------------------- + + processor 6502 + org $FF00 + +;------------------------------------------------------------------------- +; Memory declaration +;------------------------------------------------------------------------- + +XAML .EQ $24 Last "opened" location Low +XAMH .EQ $25 Last "opened" location High +STL .EQ $26 Store address Low +STH .EQ $27 Store address High +L .EQ $28 Hex value parsing Low +H .EQ $29 Hex value parsing High +YSAV .EQ $2A Used to see if hex value is given +MODE .EQ $2B $00=XAM, $7F=STOR, $AE=BLOCK XAM + +IN .EQ $0200,$027F Input buffer + +KBD .EQ $D010 PIA.A keyboard input +KBDCR .EQ $D011 PIA.A keyboard control register +DSP .EQ $D012 PIA.B display output register +DSPCR .EQ $D013 PIA.B display control register + +; KBD b7..b0 are inputs, b6..b0 is ASCII input, b7 is constant high +; Programmed to respond to low to high KBD strobe +; DSP b6..b0 are outputs, b7 is input +; CB2 goes low when data is written, returns high when CB1 goes high +; Interrupts are enabled, though not used. KBD can be jumpered to IRQ, +; whereas DSP can be jumpered to NMI. + +;------------------------------------------------------------------------- +; Constants +;------------------------------------------------------------------------- + +BS .EQ $DF Backspace key, arrow left key +CR .EQ $8D Carriage Return +ESC .EQ $9B ESC key +PROMPT .EQ "\" Prompt character + +;------------------------------------------------------------------------- +; Let's get started +; +; Remark the RESET routine is only to be entered by asserting the RESET +; line of the system. This ensures that the data direction registers +; are selected. +;------------------------------------------------------------------------- + +RESET CLD Clear decimal arithmetic mode + CLI + LDY #%0111.1111 Mask for DSP data direction reg + STY DSP (DDR mode is assumed after reset) + LDA #%1010.0111 KBD and DSP control register mask + STA KBDCR Enable interrupts, set CA1, CB1 for + STA DSPCR positive edge sense/output mode. + +; Program falls through to the GETLINE routine to save some program bytes +; Please note that Y still holds $7F, which will cause an automatic Escape + +;------------------------------------------------------------------------- +; The GETLINE process +;------------------------------------------------------------------------- + +NOTCR CMP #BS Backspace key? + BEQ BACKSPACE Yes + CMP #ESC ESC? + BEQ ESCAPE Yes + INY Advance text index + BPL NEXTCHAR Auto ESC if line longer than 127 + +ESCAPE LDA #PROMPT Print prompt character + JSR ECHO Output it. + +GETLINE LDA #CR Send CR + JSR ECHO + + LDY #0+1 Start a new input line +BACKSPACE DEY Backup text index + BMI GETLINE Oops, line's empty, reinitialize + +NEXTCHAR LDA KBDCR Wait for key press + BPL NEXTCHAR No key yet! + LDA KBD Load character. B7 should be '1' + STA IN,Y Add to text buffer + JSR ECHO Display character + CMP #CR + BNE NOTCR It's not CR! + +; Line received, now let's parse it + + LDY #-1 Reset text index + LDA #0 Default mode is XAM + TAX X=0 + +SETSTOR ASL Leaves $7B if setting STOR mode + +SETMODE STA MODE Set mode flags + +BLSKIP INY Advance text index + +NEXTITEM LDA IN,Y Get character + CMP #CR + BEQ GETLINE We're done if it's CR! + CMP #"." + BCC BLSKIP Ignore everything below "."! + BEQ SETMODE Set BLOCK XAM mode ("." = $AE) + CMP #":" + BEQ SETSTOR Set STOR mode! $BA will become $7B + CMP #"R" + BEQ RUN Run the program! Forget the rest + STX L Clear input value (X=0) + STX H + STY YSAV Save Y for comparison + +; Here we're trying to parse a new hex value + +NEXTHEX LDA IN,Y Get character for hex test + EOR #$B0 Map digits to 0-9 + CMP #9+1 Is it a decimal digit? + BCC DIG Yes! + ADC #$88 Map letter "A"-"F" to $FA-FF + CMP #$FA Hex letter? + BCC NOTHEX No! Character not hex + +DIG ASL + ASL Hex digit to MSD of A + ASL + ASL + + LDX #4 Shift count +HEXSHIFT ASL Hex digit left, MSB to carry + ROL L Rotate into LSD + ROL H Rotate into MSD's + DEX Done 4 shifts? + BNE HEXSHIFT No, loop + INY Advance text index + BNE NEXTHEX Always taken + +NOTHEX CPY YSAV Was at least 1 hex digit given? + BEQ ESCAPE No! Ignore all, start from scratch + + BIT MODE Test MODE byte + BVC NOTSTOR B6=0 is STOR, 1 is XAM or BLOCK XAM + +; STOR mode, save LSD of new hex byte + + LDA L LSD's of hex data + STA (STL,X) Store current 'store index'(X=0) + INC STL Increment store index. + BNE NEXTITEM No carry! + INC STH Add carry to 'store index' high +TONEXTITEM JMP NEXTITEM Get next command item. + +;------------------------------------------------------------------------- +; RUN user's program from last opened location +;------------------------------------------------------------------------- + +RUN JMP (XAML) Run user's program + +;------------------------------------------------------------------------- +; We're not in Store mode +;------------------------------------------------------------------------- + +NOTSTOR BMI XAMNEXT B7 = 0 for XAM, 1 for BLOCK XAM + +; We're in XAM mode now + + LDX #2 Copy 2 bytes +SETADR LDA L-1,X Copy hex data to + STA STL-1,X 'store index' + STA XAML-1,X and to 'XAM index' + DEX Next of 2 bytes + BNE SETADR Loop unless X = 0 + +; Print address and data from this address, fall through next BNE. + +NXTPRNT BNE PRDATA NE means no address to print + LDA #CR Print CR first + JSR ECHO + LDA XAMH Output high-order byte of address + JSR PRBYTE + LDA XAML Output low-order byte of address + JSR PRBYTE + LDA #":" Print colon + JSR ECHO + +PRDATA LDA #" " Print space + JSR ECHO + LDA (XAML,X) Get data from address (X=0) + JSR PRBYTE Output it in hex format +XAMNEXT STX MODE 0 -> MODE (XAM mode). + LDA XAML See if there's more to print + CMP L + LDA XAMH + SBC H + BCS TONEXTITEM Not less! No more data to output + + INC XAML Increment 'examine index' + BNE MOD8CHK No carry! + INC XAMH + +MOD8CHK LDA XAML If address MOD 8 = 0 start new line + AND #%0000.0111 + BPL NXTPRNT Always taken. + +;------------------------------------------------------------------------- +; Subroutine to print a byte in A in hex form (destructive) +;------------------------------------------------------------------------- + +PRBYTE PHA Save A for LSD + LSR + LSR + LSR MSD to LSD position + LSR + JSR PRHEX Output hex digit + PLA Restore A + +; Fall through to print hex routine + +;------------------------------------------------------------------------- +; Subroutine to print a hexadecimal digit +;------------------------------------------------------------------------- + +PRHEX AND #%0000.1111 Mask LSD for hex print + ORA #"0" Add "0" + CMP #"9"+1 Is it a decimal digit? + BCC ECHO Yes! output it + ADC #6 Add offset for letter A-F + +; Fall through to print routine + +;------------------------------------------------------------------------- +; Subroutine to print a character to the terminal +;------------------------------------------------------------------------- + +ECHO BIT DSP DA bit (B7) cleared yet? + BMI ECHO No! Wait for display ready + STA DSP Output character. Sets DA + RTS + +;------------------------------------------------------------------------- +; Vector area +;------------------------------------------------------------------------- + + .DA $0000 Unused, what a pity +NMI_VEC .DA $0F00 NMI vector +RESET_VEC .DA RESET RESET vector +IRQ_VEC .DA $0000 IRQ vector + +;------------------------------------------------------------------------- + + .LI OFF diff --git a/src/main.cpp b/src/main.cpp index a8695b9..3aa2b09 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,59 +3,69 @@ #define CHECK_BIT(var,pos) ((var) & (1<<(pos))) -const int CLOCK_PIN = 52; -const int RW_PIN = 53; -const int CLOCK_DELAY = 100; +const int SERIAL_SPEED = 115200; // Arduino Serial Speed -const int NUM_ADDR_PINS = 16; -const int NUM_DATA_PINS = 8; -const int ADDRESS_PINS[] = {44,45,2,3,4,5,6,7,8,9,10,11,12,13,46,47}; -const int DATA_PINS[] = {30,31,32,33,34,35,36,37}; +const int CLOCK_PIN = 52; // TO 6502 CLOCK +const int RW_PIN = 53; // TO 6502 R/W +const int CLOCK_DELAY = 1; // HIGH / LOW CLOCK STATE DELAY -const unsigned int ROM_ADDR = 0xFF00; -const unsigned int RAM_BANK1_ADDR = 0x0000; -const unsigned int RAM_BANK2_ADDR = 0xE000; -const unsigned int PIA_ADDR = 0xD000; +const int NUM_ADDR_PINS = 16; +const int NUM_DATA_PINS = 8; +const int ADDRESS_PINS[] = {44,45,2,3,4,5,6,7,8,9,10,11,12,13,46,47}; // TO ADDRESS PIN 1-15 6502 +const int DATA_PINS[] = {30,31,32,33,34,35,36,37}; // TO DATA BUS PIN 0-7 6502 -const unsigned int XAML = 0x24; -const unsigned int XAMH = 0x25; -const unsigned int STL = 0x26; -const unsigned int STH = 0x27; -const unsigned int L = 0x28; -const unsigned int H = 0x29; -const unsigned int YSAV = 0x2A; -const unsigned int MODE = 0x2B; +const unsigned int ROM_ADDR = 0xFF00; // ROM +const unsigned int RAM_BANK1_ADDR = 0x0000; // RAM +const unsigned int RAM_BANK2_ADDR = 0xE000; // EXTENDED RAM -const unsigned int IN = 0x200; +const unsigned int XAML = 0x24; // Last "opened" location Low +const unsigned int XAMH = 0x25; // Last "opened" location High +const unsigned int STL = 0x26; // Store address Low +const unsigned int STH = 0x27; // Store address High +const unsigned int L = 0x28; // Hex value parsing Low +const unsigned int H = 0x29; // Hex value parsing High +const unsigned int YSAV = 0x2A; // Used to see if hex value is given +const unsigned int MODE = 0x2B; // $00=XAM, $7F=STOR, $AE=BLOCK XAM +const unsigned int IN = 0x200; // Input buffer ($0200,$027F) -const int RAM_BANK_1_SIZE=4096; -const int RAM_BANK_2_SIZE=4096; +const int RAM_BANK_1_SIZE = 4096; +const int RAM_BANK_2_SIZE = 4096; unsigned char RAM_BANK_1[RAM_BANK_1_SIZE]; -unsigned int address; -unsigned char bus_data=0; -int rw_state = HIGH; - -const unsigned int KBD_ADDR = 0xD010; -const unsigned int KBDCR_ADDR = 0xD011; -const unsigned int DSP_ADDR = 0xD012; -const unsigned int DSPCR_ADDR = 0xD013; - - -unsigned char KBD = 0; -unsigned char KBDCR=0; -unsigned char DSP = 0; +// PIA MAPPING 6821 +const unsigned int PIA_ADDR = 0xD000; // PIA 6821 ADDR BASE SPACE +const unsigned int KBD_ADDR = 0xD010; // Keyb Char - B7 High on keypress +const unsigned int KBDCR_ADDR = 0xD011; // Keyb Status - B7 High on keypress / Low when ready +const unsigned int DSP_ADDR = 0xD012; // DSP Char +const unsigned int DSPCR_ADDR = 0xD013; // DSP Status - B7 Low if VIDEO ready +unsigned char KBD = 0; +unsigned char KBDCR = 0; +unsigned char DSP = 0; unsigned char DSPCR = 0; +const unsigned char BS = 0xDF; // Backspace key, arrow left key (B7 High) +const unsigned char CR = 0x8D; // Carriage Return (B7 High) +const unsigned char ESC = 0x9B; // ESC key (B7 High) + +unsigned int address; // Current address (from 6502) +unsigned char bus_data; // Data Bus value (from 6502) +int rw_state; // Current R/W state (from 6502) + + +unsigned int pre_address; // Current address (from 6502) +unsigned char pre_bus_data; // Data Bus value (from 6502) +int pre_rw_state; // Current R/W state (from 6502) + + void setupAddressPins() { for (int i = 0; i < NUM_ADDR_PINS; ++i) { - pinMode (ADDRESS_PINS[i], INPUT); + pinMode(ADDRESS_PINS[i], INPUT); } } void busMode(int mode) { for (int i = 0; i < NUM_DATA_PINS; ++i) { - pinMode (DATA_PINS[i], mode); + pinMode(DATA_PINS[i], mode); } } @@ -64,7 +74,7 @@ void readAddress() { for (int i = 0; i < NUM_ADDR_PINS; ++i) { address = address << 1; - address += (digitalRead (ADDRESS_PINS[NUM_ADDR_PINS-i-1]) == HIGH)?1:0; + address += (digitalRead(ADDRESS_PINS[NUM_ADDR_PINS-i-1]) == HIGH)?1:0; } } @@ -73,7 +83,7 @@ void readData() { for (int i = 0; i < NUM_DATA_PINS; ++i) { bus_data = bus_data << 1; - bus_data += (digitalRead (DATA_PINS[NUM_DATA_PINS-i-1]) == HIGH)?1:0; + bus_data += (digitalRead(DATA_PINS[NUM_DATA_PINS-i-1]) == HIGH)?1:0; } } @@ -82,19 +92,23 @@ void handleRWState() { if (rw_state != curent_rw_state) { rw_state=curent_rw_state; if (rw_state) { + // State HIGH - WRITE TO 6502 Data Bus busMode(OUTPUT); } else { + // State LOW - READ FROM 6502 Data Bus busMode(INPUT); } } } +// Send a byte to the 6502 DATA BUS void byteToDataBus(unsigned char data) { for (int i = 0; i < NUM_DATA_PINS; i++) { digitalWrite(DATA_PINS[i], CHECK_BIT(data, i)); } } +// READ FROM DATA BUS - STORE AT RELATED ADDRESS void readFromDataBus() { readData(); @@ -117,12 +131,14 @@ void readFromDataBus() { break; case DSP_ADDR: DSP = bus_data; - if (DSP == 0x8D) { + if (DSP == CR) { + // Simulate CR Serial.write('\r'); Serial.write('\n'); } else { Serial.write(DSP & 0x7F); } + // Display Ready - clear B7 bitClear(DSP, 7); break; case DSPCR_ADDR: @@ -133,6 +149,7 @@ void readFromDataBus() { } } +// WRITE FROM DATA BUS A BYTE FROM RELATED ADDRESS void writeToDataBus() { unsigned char val=0; @@ -147,10 +164,11 @@ void writeToDataBus() { val=ROM[address-ROM_ADDR]; break; case 0xD: - // 6821 + // PIA 6821 switch (address) { case KBD_ADDR: val=KBD; + // We'v read the char, clear B7 bitClear(KBDCR, 7); break; case KBDCR_ADDR: @@ -178,28 +196,33 @@ void handleKeyboard() { // KEYBOARD INPUT if (Serial.available() > 0) { char tempKBD = Serial.read(); + switch (tempKBD) { case 0xA: + // Not expected from KEYB + // Just ignore return; break; case 0xD: + // CR tempKBD = 0x0D; break; } KBD = tempKBD; + + // Step B7 on KBD so that the code know a new char is in bitSet(KBD, 7); bitSet(KBDCR, 7); - } } void setup() { - pinMode (CLOCK_PIN, OUTPUT); - pinMode (RW_PIN, INPUT); + pinMode(CLOCK_PIN, OUTPUT); + pinMode(RW_PIN, INPUT); setupAddressPins(); busMode(OUTPUT); - Serial.begin (115200); + Serial.begin(SERIAL_SPEED); Serial.println("----------------------------"); Serial.println("APPLE 1 REPLICA by =STID="); @@ -218,7 +241,6 @@ void setup() { } void loop () { - // LOW CLOCK digitalWrite(CLOCK_PIN, LOW); delayMicroseconds(CLOCK_DELAY); @@ -227,23 +249,25 @@ void loop () { handleRWState(); // HIGH CLOCK - digitalWrite (CLOCK_PIN, HIGH); + digitalWrite(CLOCK_PIN, HIGH); delayMicroseconds(CLOCK_DELAY); // ALWAYS READ ADDR readAddress(); // READ OR WRITE TO BUS? - if (rw_state) { - writeToDataBus(); + + if (pre_address != address || pre_rw_state != rw_state) { + rw_state ? writeToDataBus() : readFromDataBus(); } else { - readFromDataBus(); + pre_address = address; + pre_rw_state = rw_state; } handleKeyboard(); } -// WOZ TEST +// WOZ TEST (As on the Apple 1 Manual) // 0:A9 9 AA 20 EF FF E8 8A 4C 2 0 // HELLO WORLD