Reorganized folders, added pal-adapter io device folder

This commit is contained in:
Daniele Verducci su MatissePenguin
2021-01-02 16:33:51 +01:00
parent 55f5d62082
commit 68752e85a7
35 changed files with 327 additions and 1 deletions

View File

@ -0,0 +1,5 @@
pal-adapter:
@echo "Building pal adapter rom..."
@avra main.asm
@echo "Writing to ATMEGA1284..."
@minipro -w main.hex -p ATMEGA1284

View File

@ -0,0 +1,276 @@
; ***** I/O REGISTER DEFINITIONS *****************************************
; NOTE:
; Definitions marked "MEMORY MAPPED"are extended I/O ports
; and cannot be used with IN/OUT instructions
.equ UDR1 = 0xce ; MEMORY MAPPED
.equ UBRR1L = 0xcc ; MEMORY MAPPED
.equ UBRR1H = 0xcd ; MEMORY MAPPED
.equ UCSR1C = 0xca ; MEMORY MAPPED
.equ UCSR1B = 0xc9 ; MEMORY MAPPED
.equ UCSR1A = 0xc8 ; MEMORY MAPPED
.equ UDR0 = 0xc6 ; MEMORY MAPPED
.equ UBRR0L = 0xc4 ; MEMORY MAPPED
.equ UBRR0H = 0xc5 ; MEMORY MAPPED
.equ UCSR0C = 0xc2 ; MEMORY MAPPED
.equ UCSR0B = 0xc1 ; MEMORY MAPPED
.equ UCSR0A = 0xc0 ; MEMORY MAPPED
.equ TWAMR = 0xbd ; MEMORY MAPPED
.equ TWCR = 0xbc ; MEMORY MAPPED
.equ TWDR = 0xbb ; MEMORY MAPPED
.equ TWAR = 0xba ; MEMORY MAPPED
.equ TWSR = 0xb9 ; MEMORY MAPPED
.equ TWBR = 0xb8 ; MEMORY MAPPED
.equ ASSR = 0xb6 ; MEMORY MAPPED
.equ OCR2B = 0xb4 ; MEMORY MAPPED
.equ OCR2A = 0xb3 ; MEMORY MAPPED
.equ TCNT2 = 0xb2 ; MEMORY MAPPED
.equ TCCR2B = 0xb1 ; MEMORY MAPPED
.equ TCCR2A = 0xb0 ; MEMORY MAPPED
.equ OCR3BL = 0x9a ; MEMORY MAPPED
.equ OCR3BH = 0x9b ; MEMORY MAPPED
.equ OCR3AL = 0x98 ; MEMORY MAPPED
.equ OCR3AH = 0x99 ; MEMORY MAPPED
.equ ICR3L = 0x96 ; MEMORY MAPPED
.equ ICR3H = 0x97 ; MEMORY MAPPED
.equ TCNT3L = 0x94 ; MEMORY MAPPED
.equ TCNT3H = 0x95 ; MEMORY MAPPED
.equ TCCR3C = 0x92 ; MEMORY MAPPED
.equ TCCR3B = 0x91 ; MEMORY MAPPED
.equ TCCR3A = 0x90 ; MEMORY MAPPED
.equ OCR1BL = 0x8a ; MEMORY MAPPED
.equ OCR1BH = 0x8b ; MEMORY MAPPED
.equ OCR1AL = 0x88 ; MEMORY MAPPED
.equ OCR1AH = 0x89 ; MEMORY MAPPED
.equ ICR1L = 0x86 ; MEMORY MAPPED
.equ ICR1H = 0x87 ; MEMORY MAPPED
.equ TCNT1L = 0x84 ; MEMORY MAPPED
.equ TCNT1H = 0x85 ; MEMORY MAPPED
.equ TCCR1C = 0x82 ; MEMORY MAPPED
.equ TCCR1B = 0x81 ; MEMORY MAPPED
.equ TCCR1A = 0x80 ; MEMORY MAPPED
.equ DIDR1 = 0x7f ; MEMORY MAPPED
.equ DIDR0 = 0x7e ; MEMORY MAPPED
.equ ADMUX = 0x7c ; MEMORY MAPPED
.equ ADCSRB = 0x7b ; MEMORY MAPPED
.equ ADCSRA = 0x7a ; MEMORY MAPPED
.equ ADCH = 0x79 ; MEMORY MAPPED
.equ ADCL = 0x78 ; MEMORY MAPPED
.equ PCMSK3 = 0x73 ; MEMORY MAPPED
.equ TIMSK3 = 0x71 ; MEMORY MAPPED
.equ TIMSK2 = 0x70 ; MEMORY MAPPED
.equ TIMSK1 = 0x6f ; MEMORY MAPPED
.equ TIMSK0 = 0x6e ; MEMORY MAPPED
.equ PCMSK2 = 0x6d ; MEMORY MAPPED
.equ PCMSK1 = 0x6c ; MEMORY MAPPED
.equ PCMSK0 = 0x6b ; MEMORY MAPPED
.equ EICRA = 0x69 ; MEMORY MAPPED
.equ PCICR = 0x68 ; MEMORY MAPPED
.equ OSCCAL = 0x66 ; MEMORY MAPPED
.equ PRR1 = 0x65 ; MEMORY MAPPED
.equ PRR0 = 0x64 ; MEMORY MAPPED
.equ CLKPR = 0x61 ; MEMORY MAPPED
.equ WDTCSR = 0x60 ; MEMORY MAPPED
.equ SREG = 0x3f
.equ SPL = 0x3d
.equ SPH = 0x3e
.equ RAMPZ = 0x3b
.equ SPMCSR = 0x37
.equ MCUCR = 0x35
.equ MCUSR = 0x34
.equ SMCR = 0x33
.equ OCDR = 0x31
.equ ACSR = 0x30
.equ SPDR = 0x2e
.equ SPSR = 0x2d
.equ SPCR = 0x2c
.equ GPIOR2 = 0x2b
.equ GPIOR1 = 0x2a
.equ OCR0B = 0x28
.equ OCR0A = 0x27
.equ TCNT0 = 0x26
.equ TCCR0B = 0x25
.equ TCCR0A = 0x24
.equ GTCCR = 0x23
.equ EEARH = 0x22
.equ EEARL = 0x21
.equ EEDR = 0x20
.equ EECR = 0x1f
.equ GPIOR0 = 0x1e
.equ EIMSK = 0x1d
.equ EIFR = 0x1c
.equ PCIFR = 0x1b
.equ TIFR3 = 0x18
.equ TIFR2 = 0x17
.equ TIFR1 = 0x16
.equ TIFR0 = 0x15
.equ PORTD = 0x0b
.equ DDRD = 0x0a
.equ PIND = 0x09
.equ PORTC = 0x08
.equ DDRC = 0x07
.equ PINC = 0x06
.equ PORTB = 0x05
.equ DDRB = 0x04
.equ PINB = 0x03
.equ PORTA = 0x02
.equ DDRA = 0x01
.equ PINA = 0x00
; ***** PORTA ************************
; PORTA - Port A Data Register
.equ PORTA0 = 0 ; Port A Data Register bit 0
.equ PA0 = 0 ; For compatibility
.equ PORTA1 = 1 ; Port A Data Register bit 1
.equ PA1 = 1 ; For compatibility
.equ PORTA2 = 2 ; Port A Data Register bit 2
.equ PA2 = 2 ; For compatibility
.equ PORTA3 = 3 ; Port A Data Register bit 3
.equ PA3 = 3 ; For compatibility
.equ PORTA4 = 4 ; Port A Data Register bit 4
.equ PA4 = 4 ; For compatibility
.equ PORTA5 = 5 ; Port A Data Register bit 5
.equ PA5 = 5 ; For compatibility
.equ PORTA6 = 6 ; Port A Data Register bit 6
.equ PA6 = 6 ; For compatibility
.equ PORTA7 = 7 ; Port A Data Register bit 7
.equ PA7 = 7 ; For compatibility
; DDRA - Port A Data Direction Register
.equ DDA0 = 0 ; Data Direction Register, Port A, bit 0
.equ DDA1 = 1 ; Data Direction Register, Port A, bit 1
.equ DDA2 = 2 ; Data Direction Register, Port A, bit 2
.equ DDA3 = 3 ; Data Direction Register, Port A, bit 3
.equ DDA4 = 4 ; Data Direction Register, Port A, bit 4
.equ DDA5 = 5 ; Data Direction Register, Port A, bit 5
.equ DDA6 = 6 ; Data Direction Register, Port A, bit 6
.equ DDA7 = 7 ; Data Direction Register, Port A, bit 7
; PINA - Port A Input Pins
.equ PINA0 = 0 ; Input Pins, Port A bit 0
.equ PINA1 = 1 ; Input Pins, Port A bit 1
.equ PINA2 = 2 ; Input Pins, Port A bit 2
.equ PINA3 = 3 ; Input Pins, Port A bit 3
.equ PINA4 = 4 ; Input Pins, Port A bit 4
.equ PINA5 = 5 ; Input Pins, Port A bit 5
.equ PINA6 = 6 ; Input Pins, Port A bit 6
.equ PINA7 = 7 ; Input Pins, Port A bit 7
; ***** PORTB ************************
; PORTB - Port B Data Register
.equ PORTB0 = 0 ; Port B Data Register bit 0
.equ PB0 = 0 ; For compatibility
.equ PORTB1 = 1 ; Port B Data Register bit 1
.equ PB1 = 1 ; For compatibility
.equ PORTB2 = 2 ; Port B Data Register bit 2
.equ PB2 = 2 ; For compatibility
.equ PORTB3 = 3 ; Port B Data Register bit 3
.equ PB3 = 3 ; For compatibility
.equ PORTB4 = 4 ; Port B Data Register bit 4
.equ PB4 = 4 ; For compatibility
.equ PORTB5 = 5 ; Port B Data Register bit 5
.equ PB5 = 5 ; For compatibility
.equ PORTB6 = 6 ; Port B Data Register bit 6
.equ PB6 = 6 ; For compatibility
.equ PORTB7 = 7 ; Port B Data Register bit 7
.equ PB7 = 7 ; For compatibility
; DDRB - Port B Data Direction Register
.equ DDB0 = 0 ; Port B Data Direction Register bit 0
.equ DDB1 = 1 ; Port B Data Direction Register bit 1
.equ DDB2 = 2 ; Port B Data Direction Register bit 2
.equ DDB3 = 3 ; Port B Data Direction Register bit 3
.equ DDB4 = 4 ; Port B Data Direction Register bit 4
.equ DDB5 = 5 ; Port B Data Direction Register bit 5
.equ DDB6 = 6 ; Port B Data Direction Register bit 6
.equ DDB7 = 7 ; Port B Data Direction Register bit 7
; PINB - Port B Input Pins
.equ PINB0 = 0 ; Port B Input Pins bit 0
.equ PINB1 = 1 ; Port B Input Pins bit 1
.equ PINB2 = 2 ; Port B Input Pins bit 2
.equ PINB3 = 3 ; Port B Input Pins bit 3
.equ PINB4 = 4 ; Port B Input Pins bit 4
.equ PINB5 = 5 ; Port B Input Pins bit 5
.equ PINB6 = 6 ; Port B Input Pins bit 6
.equ PINB7 = 7 ; Port B Input Pins bit 7
; ***** PORTC ************************
; PORTC - Port C Data Register
.equ PORTC0 = 0 ; Port C Data Register bit 0
.equ PC0 = 0 ; For compatibility
.equ PORTC1 = 1 ; Port C Data Register bit 1
.equ PC1 = 1 ; For compatibility
.equ PORTC2 = 2 ; Port C Data Register bit 2
.equ PC2 = 2 ; For compatibility
.equ PORTC3 = 3 ; Port C Data Register bit 3
.equ PC3 = 3 ; For compatibility
.equ PORTC4 = 4 ; Port C Data Register bit 4
.equ PC4 = 4 ; For compatibility
.equ PORTC5 = 5 ; Port C Data Register bit 5
.equ PC5 = 5 ; For compatibility
.equ PORTC6 = 6 ; Port C Data Register bit 6
.equ PC6 = 6 ; For compatibility
.equ PORTC7 = 7 ; Port C Data Register bit 7
.equ PC7 = 7 ; For compatibility
; DDRC - Port C Data Direction Register
.equ DDC0 = 0 ; Port C Data Direction Register bit 0
.equ DDC1 = 1 ; Port C Data Direction Register bit 1
.equ DDC2 = 2 ; Port C Data Direction Register bit 2
.equ DDC3 = 3 ; Port C Data Direction Register bit 3
.equ DDC4 = 4 ; Port C Data Direction Register bit 4
.equ DDC5 = 5 ; Port C Data Direction Register bit 5
.equ DDC6 = 6 ; Port C Data Direction Register bit 6
.equ DDC7 = 7 ; Port C Data Direction Register bit 7
; PINC - Port C Input Pins
.equ PINC0 = 0 ; Port C Input Pins bit 0
.equ PINC1 = 1 ; Port C Input Pins bit 1
.equ PINC2 = 2 ; Port C Input Pins bit 2
.equ PINC3 = 3 ; Port C Input Pins bit 3
.equ PINC4 = 4 ; Port C Input Pins bit 4
.equ PINC5 = 5 ; Port C Input Pins bit 5
.equ PINC6 = 6 ; Port C Input Pins bit 6
.equ PINC7 = 7 ; Port C Input Pins bit 7
; ***** PORTD ************************
; PORTD - Port D Data Register
.equ PORTD0 = 0 ; Port D Data Register bit 0
.equ PD0 = 0 ; For compatibility
.equ PORTD1 = 1 ; Port D Data Register bit 1
.equ PD1 = 1 ; For compatibility
.equ PORTD2 = 2 ; Port D Data Register bit 2
.equ PD2 = 2 ; For compatibility
.equ PORTD3 = 3 ; Port D Data Register bit 3
.equ PD3 = 3 ; For compatibility
.equ PORTD4 = 4 ; Port D Data Register bit 4
.equ PD4 = 4 ; For compatibility
.equ PORTD5 = 5 ; Port D Data Register bit 5
.equ PD5 = 5 ; For compatibility
.equ PORTD6 = 6 ; Port D Data Register bit 6
.equ PD6 = 6 ; For compatibility
.equ PORTD7 = 7 ; Port D Data Register bit 7
.equ PD7 = 7 ; For compatibility
; DDRD - Port D Data Direction Register
.equ DDD0 = 0 ; Port D Data Direction Register bit 0
.equ DDD1 = 1 ; Port D Data Direction Register bit 1
.equ DDD2 = 2 ; Port D Data Direction Register bit 2
.equ DDD3 = 3 ; Port D Data Direction Register bit 3
.equ DDD4 = 4 ; Port D Data Direction Register bit 4
.equ DDD5 = 5 ; Port D Data Direction Register bit 5
.equ DDD6 = 6 ; Port D Data Direction Register bit 6
.equ DDD7 = 7 ; Port D Data Direction Register bit 7
; PIND - Port D Input Pins
.equ PIND0 = 0 ; Port D Input Pins bit 0
.equ PIND1 = 1 ; Port D Input Pins bit 1
.equ PIND2 = 2 ; Port D Input Pins bit 2
.equ PIND3 = 3 ; Port D Input Pins bit 3
.equ PIND4 = 4 ; Port D Input Pins bit 4
.equ PIND5 = 5 ; Port D Input Pins bit 5
.equ PIND6 = 6 ; Port D Input Pins bit 6
.equ PIND7 = 7 ; Port D Input Pins bit 7

View File

@ -0,0 +1,31 @@
.include "atmega1284definition.asm"
; define constant
.equ LED_PIN = PD7 ; use PD7 as LED pin
; start vector
.org 0x0000
rjmp main ; jump to main label
; main program
main:
sbi DDRD, LED_PIN ; set LED pin as output
loop:
sbic PIND, LED_PIN ; if bit of LED pin is clear, skip next line
cbi PORTD, LED_PIN ; if 1, turn the LED off
sbis PIND, LED_PIN ; if bit of LED pin is set, skip next line
sbi PORTD, LED_PIN ; if 0, light the LED up
delay_500ms:
ldi r20, 32 ; set register, r20 = 32
delay2:
ldi r19, 64 ; set register, r19 = 64
delay1:
ldi r18, 128 ; set register, r18 = 128
delay0:
dec r18 ; decrement register, r18 = r18 - 1
brne delay0 ; if r18 != 0, jump to label delay0
dec r19 ; decrement register, r19 = r19 -1
brne delay1 ; if r19 != 0, jump to label delay1
dec r20 ; decrement register, r20 = r20 -1
brne delay2 ; if r20 != 0, jump to label delay2
rjmp loop ; if r20 == 0, jump to label loop

View File

@ -0,0 +1 @@
:00000001FF

View File

@ -0,0 +1,4 @@
:020000020000FC
:1000000000C0579A4F995F984F9B5F9A40E230E447
:1000100020E82A95F1F73A95D9F74A95C1F7F2CF3A
:00000001FF

View File

@ -0,0 +1,78 @@
/**
* 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 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), 11 (WR) and 12 (RS) is input
Serial.begin(2000000);
Serial.println("Pat80 terminal");
attachInterrupt(digitalPinToInterrupt(2), onClk, CHANGE);
}
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)) {
// Printable character
Serial.print((char)outgoingBuffer);
} else {
// Non-printable character
Serial.print("[0x");
Serial.print(outgoingBuffer, HEX);
Serial.print("]");
}
outgoingBuffer = 0;
}
}
void onClk() {
// In any case, return to high impedance state
DDRD = B00000010;
DDRB = B00000000;
if ((PIND & B00000100) == 0) {
// EN is LOW: Clock pulse started
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
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
}
}
}

View File

@ -0,0 +1,153 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
""" @package docstring
ARDUINO PARALLEL TERMINAL EMULATOR
USAGE:
Connect the arduino to a Pat80 I/O port.
Flash /arduino/arduino_terminal firmware into the Arduino.
Connect the Arduino to a PC via USB and power on Pat80
Run this program providing the Arduino USB port
DISCLAIMER:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import serial
import curses
import time
import textwrap
import os
class TerminalEmulator:
SYNC_SLEEP = 0.001
def __init__(self, w, ser):
w.clear()
w.move(0,0)
while True:
# read serial port and write to curses
if ser.inWaiting():
b = ser.read(1)
if ord(b) > 31 or ord(b) == 10:
w.addch(b)
# read key and write to serial port
key = w.getch()
if key == 10 or (key > 31 and key < 256):
# Is a character
time.sleep(self.SYNC_SLEEP)
ser.write(bytes([key]))
elif int(key) == 1: # CTRL+A, enter ADB mode
# Save cursor position
(xPos, yPos) = w.getyx()
self.adbMode(w, ser)
# Restore cursor position
w.move(xPos, yPos)
w.refresh()
def adbMode(self, w, ser):
stdscr.nodelay(False)
curses.echo()
# Clear first line
w.move(0,0)
w.clrtoeol()
# Ask for file path
w.addstr(0, 0, '[ADB MODE] file to load:', curses.A_REVERSE)
path = w.getstr()
try:
header = bytearray(2)
size = os.path.getsize(path)
# Compute the two header bytes needed to declare the length of the stream
header[1] = size & 255 # get lower 8 bits
size >>= 8 # shift by 8 bits
header[0] = size & 255 # get second lower 8 bits
# Log size for debug
w.addstr("Header bytes: {}".format(header.hex()))
w.refresh()
# Send the two heading bytes (most significant first)
ser.write(header[0:1])
time.sleep(self.SYNC_SLEEP)
ser.write(header[1:2])
time.sleep(self.SYNC_SLEEP)
# Send the actual binary stream
with open(path, "rb") as f:
byte = f.read(1)
while byte:
# Check if terminal interface (Arduino) is busy
ser.write(b'\x01') # COMMAND_BUFFER
ser.read()
ser.write(byte)
byte = f.read(1)
except IOError as e:
w.move(0,0)
w.clrtoeol()
w.addstr(" {}".format(str(e)), curses.A_REVERSE)
w.refresh()
curses.noecho()
stdscr.nodelay(True)
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(
formatter_class=argparse.RawTextHelpFormatter,
epilog=textwrap.dedent('''\
Pat80 Terminal Emulator with ADB (Assembly Deploy Bridge) support.
CTRL+C Exits
CTRL+A ADB mode: sends binary file
''')
)
parser.add_argument('port', help="arduino parallel monitor USB port")
parser.add_argument('baudrate', help="arduino parallel monitor USB baudrate")
args = parser.parse_args()
# Init curses
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.idlok(True)
stdscr.scrollok(True)
stdscr.nodelay(True)
exitMessage = None
exitSuccess = True
try:
ser = serial.Serial(args.port, args.baudrate, timeout=0)
td = TerminalEmulator(stdscr, ser)
except KeyboardInterrupt:
exitMessage = 'Bye!'
exitSuccess = True
except Exception as e:
exitMessage = str(e)
exitSuccess = False
finally:
# Close serial
ser.close()
# Stop curses
curses.nocbreak()
curses.echo()
curses.endwin()
# Print exit message
print(exitMessage)
exit(0 if exitSuccess else 1)