WIP reimplementing serial terminal with DATA_AVAILABLE register
This commit is contained in:
parent
f1e7622e17
commit
2c9675b8f0
@ -2,19 +2,28 @@
|
||||
* Terminal interface.
|
||||
* This sketch allow an Arduino to be used as a terminal to log into Pat80.
|
||||
* The Arduino is connected to the Pat80 I/O bus and to the terminal computer via USB.
|
||||
* The Arduino IDE serial monitor is used to send and receive commands to the Z80.
|
||||
* The Python Terminal Monitor or the Arduino IDE serial monitor is used to send
|
||||
* and receive commands to/from the Z80.
|
||||
*
|
||||
* Seen from the Pat80, the terminal interface has two registers:
|
||||
* DATA Register at addr 0x00 (\RS) contains the last received byte from the pc
|
||||
* DATA_AVAILABLE Register at addr 0x01 (RS) contains the number of bytes in the buffer,
|
||||
* waiting to be read from the Pat80. A READ operation on DATA register removes the
|
||||
* byte from the buffer and decrements DATA_AVAILABLE.
|
||||
*/
|
||||
|
||||
// EN 2 // Input, Active low
|
||||
// WR 11 // Input, Active low
|
||||
// RS 12 // Input, low = DATA register, high = DATA_AVAILABLE register
|
||||
// DATA BUS (Input/Output, active high): 3, 4, 5, 6, 7, 8, 9, 10;
|
||||
|
||||
byte incomingBuffer = 0; // Incoming from computer, to the Pat80
|
||||
byte outgoingBuffer = 0; // Outgoing to computer, from the Pat80
|
||||
byte availableBytes = 0; // Available bytes in the incoming buffer (for the DATA_AVAILABLE register)
|
||||
|
||||
void setup() {
|
||||
DDRD = B00000010; // Port D (used arduino pins 2 (EN) and 3 to 7 (DATA)) is input. Avoid changing serial pins.
|
||||
DDRB = B00000000; // Port B (used arduino pins 8 to 10 (DATA) and 11 (WR)) is input
|
||||
DDRB = B00000000; // Port B (used arduino pins 8 to 10 (DATA), 11 (WR) and 12 (RS) is input
|
||||
|
||||
Serial.begin(2000000);
|
||||
Serial.println("Pat80 terminal");
|
||||
@ -25,6 +34,7 @@ void setup() {
|
||||
void loop() {
|
||||
if (Serial.available() > 0) {
|
||||
incomingBuffer = Serial.read();
|
||||
availableBytes = 1; // TODO: Implement a 256 byte buffer and store the avail bytes number in this var
|
||||
}
|
||||
if (outgoingBuffer != 0) {
|
||||
if ((outgoingBuffer >= 8 && outgoingBuffer <= 13) || (outgoingBuffer >= 32 && outgoingBuffer <= 127)) {
|
||||
@ -49,10 +59,17 @@ void onClk() {
|
||||
if ((PINB & B00001000) == B00001000) { // WR is HIGH (Pat80 wants to Read (we send data))
|
||||
DDRD = DDRD | B11111000; // Port D (arduino pins 3 to 7) is output. In or to preserve serial pins and interrupt pin
|
||||
DDRB = B00000111; // Port B (0,1,2) = pins 8,9,10 output
|
||||
// Split byte to two parts
|
||||
PORTD = incomingBuffer << 3;
|
||||
PORTB = incomingBuffer >> 5;
|
||||
incomingBuffer = 0;
|
||||
if ((PINB & B00010000) == B00010000) { // RS is HIGH: we send number of bytes available in buffer
|
||||
// Split byte to two parts
|
||||
PORTD = availableBytes << 3;
|
||||
PORTB = availableBytes >> 5;
|
||||
} else {
|
||||
// Split byte to two parts
|
||||
PORTD = incomingBuffer << 3;
|
||||
PORTB = incomingBuffer >> 5;
|
||||
incomingBuffer = 0;
|
||||
availableBytes = 0;
|
||||
}
|
||||
} else {
|
||||
// Pat80 wants to Write (we receive data)
|
||||
outgoingBuffer = (PIND >> 3) | (PINB << 5); // Compose the final byte from the two parts
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
; config (IO port 0)
|
||||
TERM_DATA_REG: EQU IO_0
|
||||
TERM_DATA_AVAIL_REG: EQU IO_0 + 1
|
||||
|
||||
; variables
|
||||
TERM_VAR_SPACE: EQU DRV_VAR_SPACE + 128
|
||||
@ -26,7 +27,9 @@ Term_printc:
|
||||
out (TERM_DATA_REG),a
|
||||
ret
|
||||
|
||||
; Reads a single character. 0s are ignored (can be used with keyboard)
|
||||
; Reads a single character. 0s are ignored (can be used with keyboard).
|
||||
; Doesn't check DATA_AVAILABLE register of parallel port, because a 0 byte
|
||||
; is ignored anyway (it represents the ASCII NUL control char).
|
||||
; @return A The read character
|
||||
Term_readc:
|
||||
in a, (TERM_DATA_REG) ; reads a character
|
||||
@ -35,6 +38,8 @@ Term_readc:
|
||||
ret ; if not NULL, returns it in the a register
|
||||
|
||||
; Reads a line. 0s are ignored (can be used with keyboard)
|
||||
; Doesn't check DATA_AVAILABLE register of parallel port, because a 0 byte
|
||||
; is ignored anyway (it represents the ASCII NUL control char).
|
||||
; @return BC The pointer to a null-terminated read string
|
||||
Term_readline:
|
||||
ld bc, incoming_string ; this array will contain read string
|
||||
@ -56,9 +61,17 @@ Term_readline:
|
||||
ld bc, incoming_string ; Returns read string pointer
|
||||
ret
|
||||
|
||||
; Reads the byte currently on the I/O bus at the provided address.
|
||||
; Returns the number of bytes available on the parallel port using the
|
||||
; DATA_AVAILABLE register.
|
||||
; @return a the number of available bytes
|
||||
Term_availb:
|
||||
in a, (TERM_DATA_AVAIL_REG)
|
||||
ret
|
||||
|
||||
; Reads the first available byte on the serial port using the DATA register.
|
||||
; 0s are not ignored (cannot be used with keyboard)
|
||||
; Affects NO condition bits!
|
||||
; @return the available byte, even if 0
|
||||
Term_readb:
|
||||
in a, (TERM_DATA_REG) ; reads a byte
|
||||
ret
|
@ -25,6 +25,7 @@ MON_ARG_HEX: DB " 0x",0
|
||||
MON_HELP: DB 10,"Available commands:\nHELP prints this message\nDUMP shows memory content\nSET sets memory content LOAD\nRUN executes code\nADB starts Assembly Deploy Bridge",0
|
||||
MON_MSG_ADB: DB 10,"Waiting for data.",0
|
||||
MON_ERR_SYNTAX: DB " Syntax error",0
|
||||
;MON_ADB_TIMEOUT: EQU 0xFF // Number of cycles after an ADB binary transfer is considered completed
|
||||
|
||||
Monitor_main:
|
||||
; Print welcome string
|
||||
@ -101,8 +102,10 @@ monitor_adb:
|
||||
call Print
|
||||
; start copying incoming data to application space
|
||||
call monitor_copyTermToAppMem
|
||||
jp APP_SPACE ; Start executing code
|
||||
;jp monitor_main_loop
|
||||
;jp APP_SPACE ; Start executing code
|
||||
ld bc, APP_SPACE
|
||||
call Print
|
||||
jp monitor_main_loop
|
||||
|
||||
; Read 1 hex byte (e.g. 0x8C)
|
||||
monitor_arg_byte:
|
||||
@ -160,22 +163,21 @@ monitor_readHexDigit:
|
||||
ret
|
||||
|
||||
; Copy data from STDIN to application memory. This is tought to be used with parallel terminal, not keyboard:
|
||||
; 0s are not ignored and the sequence is complete when found 8 zeros.
|
||||
; 0s are not ignored and the sequence is complete when no data is available for 8 cpu cycles.
|
||||
monitor_copyTermToAppMem:
|
||||
call Term_readb
|
||||
cp 0
|
||||
jp z, monitor_copyTermToAppMem ; wait for data stream to begin: ignore leading zeros
|
||||
ld hl, APP_SPACE ; we will write in APP_SPACE
|
||||
ld b, 8 ; the number of zeros that represent the end of stream
|
||||
ld b, 255; MON_ADB_TIMEOUT ; the timeout counter (number cycles without available data that represent the end of stream)
|
||||
monitor_copyTermToAppMem_loop:
|
||||
dec b ; decrement the timeout counter
|
||||
ret 0 ; if counter is 0, timeout reached: return
|
||||
; check if bytes are available
|
||||
call Term_availb
|
||||
cp 0
|
||||
jp z, monitor_copyTermToAppMem ; no bytes available, next loop
|
||||
; bytes are available
|
||||
ld b, 255 ;MON_ADB_TIMEOUT; reset the counter
|
||||
ld (hl), a ; copy byte to memory
|
||||
inc hl ; move to next memory position
|
||||
cp 0 ; compare A to 0
|
||||
; load next byte to A (this doesn't affect condition bits, so flag Z from previous cp is still valid)
|
||||
call Term_readb
|
||||
jp nz, monitor_copyTermToAppMem_loop ; if during previous cp A was not 0, execute next cycle
|
||||
dec b ; if A is 0, decrement "end of stream" counter
|
||||
ret z ; if B is 0, we found 8 zeros, so the stream is finished: return.
|
||||
jp monitor_copyTermToAppMem_loop ; otherwise, continue loop
|
||||
jp monitor_copyTermToAppMem_loop ; continue loop
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user