diff --git a/address_decoder.jed b/address_decoder.jed index 30600cf..d5b088d 100644 --- a/address_decoder.jed +++ b/address_decoder.jed @@ -2,7 +2,7 @@ GAL20V8 EQN2JED - Boolean Equations to JEDEC file assembler (Version V101) Copyright (c) National Semiconductor Corporation 1990-1993 -Assembled from "e:/APPLE1~1/ADDRES~1.EQN". Date: 5-24-120 +Assembled from "c:/APPLE1~1/ADDRES~1.EQN". Date: 6-7-120 * NOTE PINS RW:2 A0:3 A1:4 A2:5 A3:6 A4:7 A5:8 A6:9 A7:10 A8:11* NOTE PINS GND:12 A9:14 A10:15 A11:16 SR:17 RD:18 WD:19 ROM:20* @@ -19,7 +19,7 @@ L0640 L0960 1011011010011011101110111010101001101011* L1280 -0111101010011011101110111010101001101011* +0111101010111011101110111010101001101011* L1600 0111101010111011101110111010101010101011* L2560 @@ -30,5 +30,5 @@ L2640 0000000010000000111100001000000010000000100000000000000000000000* L2704 10* -C1FC0* +C1FC4* 0000 diff --git a/addressdecoder.eqn b/addressdecoder.eqn index 8eb818d..e09b21c 100644 --- a/addressdecoder.eqn +++ b/addressdecoder.eqn @@ -7,7 +7,7 @@ R=23 VCC=24 equations SR = /A0 * /A1 * /A2 * /A3 * /A4 * /A5 * /A6 * /A7 * /A8 * /A9 * /A10 * /A11 * /R * RW -RD = /A0 * /A1 * /A2 * /A3 * /A4 * /A5 * /A6 * A7 * /A8 * /A9 * /A10 * /A11 * /R * RW * PHI +RD = /A0 * /A1 * /A2 * /A3 * /A4 * /A5 * /A6 * A7 * /A8 * /A9 * /A10 * /A11 * /R * RW WD = A0 * /A1 * /A2 * /A3 * /A4 * /A5 * /A6 * A7 * /A8 * /A9 * /A10 * /A11 * /R * /RW * PHI /ROM = A8 * /R * RW + A9 * /R * RW diff --git a/firmware/main.c b/firmware/main.c index eac787d..0dcc507 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -21,6 +21,8 @@ #define DATA6 PD3 #define DATA7 PD4 +#define BUFFER_SIZE 8 + typedef enum {NONE, READ, WRITE} mode_t; mode_t mode = NONE; @@ -31,6 +33,10 @@ uint8_t lower_part = 0x00; uint8_t data_write_interrupt_count = 0; uint8_t data_read_interrupt_count = 0; +// receive buffer +uint8_t receive_buffer[BUFFER_SIZE]; +int8_t receive_index = -1; + // Registers: PCMSK0, PCMSK1, PCMSK2 :registers that enable or disable pin-change interrupts // on individual pins @@ -46,38 +52,46 @@ inline void not_ready() { PORTD &= ~(_BV(STATUS)); } -void setup() { +inline void put_data() { + upper_part = (PORTD & 0xe3) | ((0xe0 & receive_buffer[0])>>3); + lower_part = (PORTB & 0xc1) | ((0x1f & receive_buffer[0])<<1); + PORTD = upper_part; + PORTB = lower_part; +} + +void setup() { + // set input on DATA_READ_LINE DDRB &= ~(_BV(DATA_READ_LINE)); // interrupt on DATA_READ_LINE change PCMSK0 |= _BV(PCINT0); PCICR |= _BV(PCIE0); - + // set input on DATA_WRITE_LINE DDRD &= ~(_BV(DATA_WRITE_LINE)); // interrupt on DATA_WRITE_LINE change PCMSK2 |= _BV(PCINT23); PCICR |= _BV(PCIE2); - + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - + UCSR0A = 0x00; UCSR0C = 0x00; // 8 bits of data, 1 stop bit, no parity UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); // TXD pullup PORTD |= _BV(PD1); - + // interrupt on DATA_READ_LINE change PCMSK0 |= _BV(PCINT0); PCICR |= _BV(PCIE0); - + // set output on status DDRD |= _BV(STATUS); not_ready(); - + // enable global interrupts sei(); } @@ -87,15 +101,34 @@ ISR(PCINT0_vect) { if (data_read_interrupt_count == 0) { if (mode != READ) { mode = READ; - + // enable RXD and it's interrupt UCSR0B = _BV(RXEN0) | _BV(RXCIE0); - + // set output on data pins DDRD |= _BV(DATA5) | _BV(DATA6) | _BV(DATA7); DDRB |= _BV(DATA0) | _BV(DATA1) | _BV(DATA2) | _BV(DATA3) | _BV(DATA4); + + receive_index = -1; + not_ready(); + data_read_interrupt_count = 1; + return; + } + + if (receive_index > -1) { + uint8_t i; + for (i = 1; i <= receive_index; i++) { + receive_buffer[i - 1] = receive_buffer[i]; + } + receive_index--; + + if (receive_index == -1) { + not_ready(); + } else { + // put next byte from receive buffer + put_data(); + } } - not_ready(); data_read_interrupt_count = 1; } else { data_read_interrupt_count = 0; @@ -106,18 +139,18 @@ ISR(PCINT0_vect) { ISR(PCINT2_vect) { upper_part = PINB; lower_part = PIND; - + if (data_write_interrupt_count == 0) { if (mode == WRITE) { upper_part = upper_part >> 1; upper_part &= 0x1f; - + lower_part = lower_part << 3; lower_part &= 0xe0; - + // set status to not ready PORTD &= ~(_BV(STATUS)); - + // send byte loop_until_bit_is_set(UCSR0A, UDRE0); UDR0 = upper_part | lower_part; @@ -128,14 +161,14 @@ ISR(PCINT2_vect) { PORTB &= 0xc1; } mode = WRITE; - + // enable TXD interrupt and it's interrupt UCSR0B = _BV(TXEN0) | _BV(TXCIE0); - + // set input on data pins DDRD &= ~(_BV(DATA5) | _BV(DATA6) | _BV(DATA7)); DDRB &= ~(_BV(DATA0) | _BV(DATA1) | _BV(DATA2) | _BV(DATA3) | _BV(DATA4)); - + ready(); } data_write_interrupt_count = 1; @@ -149,11 +182,14 @@ ISR(USART_RX_vect) if (mode == READ) { data = UDR0; - upper_part = (PORTD & 0xe3) | ((0xe0 & data)>>3); - lower_part = (PORTB & 0xc1) | ((0x1f & data)<<1); + if (receive_index >= BUFFER_SIZE - 1) { + receive_index = -1; + } - PORTD = upper_part; - PORTB = lower_part; + receive_buffer[++receive_index] = data; + + // always put first byte from receive buffer + put_data(); ready(); } @@ -168,10 +204,9 @@ ISR(USART_TX_vect) int main(void) { setup(); - + for(;;){ // only interrupt driven } return 0; /* never reached */ } - diff --git a/src/apple1serial.xa b/src/apple1serial.xa index fe4265b..b4fccbe 100644 --- a/src/apple1serial.xa +++ b/src/apple1serial.xa @@ -1,10 +1,15 @@ ;End address of dump block -#define hex1_l $50 -#define hex1_h $51 +#define hex1_l $24 +#define hex1_h $25 ;Begin address of dump block -#define hex2_l $52 -#define hex2_h $53 +#define hex2_l $26 +#define hex2_h $27 + +#define last_command $28 +#define last_command_none $00 +#define last_command_read $01 +#define last_command_write $02 ;Input buffer #define input $0200 @@ -44,6 +49,8 @@ apple_serial jsr echo lda #CR ;And drop the cursor one line jsr echo + lda #$00 ;Set last command type to NONE + sta last_command ldy #$FF ;Reset the input buffer index next_char @@ -133,28 +140,16 @@ separator sta hex1_h jmp next_chr -reset - txa - pha - lda serial_reset - ldx #$00 - ldy #$00 -reset_loop ; ((2 + 2 + 3) * 255 + 2 + 3) * 255 = - nop ; 2 cycles - iny ; 2 cycles - bne reset_loop ; 3 cycles - inx ; 2 cycles - bne reset_loop ; 3 cycles - pla - tax - rts - ;------------------------------------------------------------------------- ; Read procedure ;------------------------------------------------------------------------- read + lda last_command + cmp #last_command_read + beq read_ready lda serial_read ;Enable read mode, this can be done quick, without reset +read_ready ldy #$00 read_byte @@ -171,6 +166,8 @@ read_byte cmp hex1_h ;Compare upper destination address half with upper end address half bne read_next ;If not equal then proceed to read next byte + lda last_command_read ;Set last command to READ + sta last_command jmp next_cmd ;Read is completed, proceed to next command read_next @@ -187,10 +184,14 @@ read_next ;------------------------------------------------------------------------- write + lda last_command + cmp #last_command_write + beq write_ready jsr reset ;Reset serial and give some time to stabilize ;This is required due to inability to guess what is the current device mode ;and prevents from polluting the output while setting the write mode sta serial_write ;Enable write mode +write_ready ldy #$00 write_byte @@ -207,6 +208,8 @@ write_byte cmp hex1_h ;Compare upper source address half with upper end address half bne write_next ;If not equal then proceed to write next byte + lda last_command_write ;Set last command to WRITE + sta last_command jmp next_cmd ;Write is completed, proceed to next command write_next @@ -222,6 +225,30 @@ write_next ; tool routines ;------------------------------------------------------------------------- +reset + txa ;Preserve X on stack + pha + + tya ;Preserve Y on stack + pha + + lda serial_reset ;Reset + ldx #$00 + ldy #$00 +reset_loop ; ~((2 + 2 + 3) * 255 + 2 + 3) * 255 = + nop ; 2 cycles + iny ; 2 cycles + bne reset_loop ; 3 cycles + inx ; 2 cycles + bne reset_loop ; 3 cycles + + pla ;Restore Y from stack + tay + + pla ;Restore X from stack + tax + rts + increment_16bit inc $00,X bne increment_16bit_done diff --git a/src/tests.xa b/src/tests.xa index c1fc583..1cad4f4 100644 --- a/src/tests.xa +++ b/src/tests.xa @@ -5,12 +5,12 @@ #define serial_read $C080 #define serial_write $C081 -* = $C200 +* = $C300 .dsb (*-end_of_apple1serial), 0 ; teletype on apple-1 -* = $C200 -teletype_apple1 = $C200 +* = $C300 +teletype_apple1 = $C300 lda serial_read wait lda serial_ready @@ -20,16 +20,12 @@ wait jmp wait end_of_teletype_apple1 -; AD 80 C0 AD 00 C0 F0 FB -; AD 80 C0 20 EF FF 4C 03 -; 00 - ; teletype on remote -* = $C300 +* = $C400 .dsb (*-end_of_teletype_apple1), 0 -* = $C300 -teletype_remote = $C300 +* = $C400 +teletype_remote = $C400 lda #$FF sta serial_write get_key @@ -42,16 +38,12 @@ get_key jmp get_key end_of_teletype_remote -; A9 FF 8D 81 C0 AD 11 D0 -; 10 FB AD 10 D0 38 E9 A0 -; 8D 81 C0 4C 85 02 - ; 0-255 repeating counter over TXD -* = $C400 +* = $C500 .dsb (*-end_of_teletype_remote), 0 -* = $C400 -counter_remote = $C400 +* = $C500 +counter_remote = $C500 ldy #$00 sta serial_write check_ready @@ -61,7 +53,4 @@ check_ready sta serial_write iny jmp check_ready - -; A0 00 8D 81 C0 AD 00 C0 -; F0 FB 98 8D 81 C0 C8 4C -; 85 02 +