mirror of
https://github.com/flowenol/apple1serial.git
synced 2024-12-26 14:29:29 +00:00
read buffer & last operation
This commit is contained in:
parent
7de77dd557
commit
f05389366d
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
31
src/tests.xa
31
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user