summaryrefslogtreecommitdiffstats
path: root/sw/z80
diff options
context:
space:
mode:
authorNao Pross <naopross@thearcway.org>2017-08-28 13:55:35 +0200
committerNao Pross <naopross@thearcway.org>2017-08-28 13:55:35 +0200
commit9b9e656da951138f7d5523fd717c86a834211096 (patch)
tree397be6d5fb2ea3566efcf7d6684660e8a2ab9593 /sw/z80
parentupdate gitignore to ignore sdcc output (diff)
downloadz80uPC-9b9e656da951138f7d5523fd717c86a834211096.tar.gz
z80uPC-9b9e656da951138f7d5523fd717c86a834211096.zip
add test program for z80
Diffstat (limited to '')
-rw-r--r--sw/z80_test/crt0.rel86
-rw-r--r--sw/z80_test/crt0.s4
-rw-r--r--sw/z80_test/ctc.c7
-rw-r--r--sw/z80_test/ctc.h6
-rw-r--r--sw/z80_test/devices.h15
-rw-r--r--sw/z80_test/main.c7
-rw-r--r--sw/z80_test/makefile12
-rw-r--r--sw/z80_test/pio.c40
-rw-r--r--sw/z80_test/pio.h37
-rw-r--r--sw/z80_test/types.h13
-rw-r--r--sw/z80_test/usart.c91
-rw-r--r--sw/z80_test/usart.h155
12 files changed, 463 insertions, 10 deletions
diff --git a/sw/z80_test/crt0.rel b/sw/z80_test/crt0.rel
new file mode 100644
index 0000000..809c0e6
--- /dev/null
+++ b/sw/z80_test/crt0.rel
@@ -0,0 +1,86 @@
+XL2
+H 14 areas 5 global symbols
+M crt0
+S _main Ref0000
+S .__.ABS. Def0000
+A _CODE size A flags 0 addr 0
+S __clock Def0000
+S _exit Def0004
+A _HEADER size 0 flags 8 addr 0
+A _HEADER0 size 3 flags 8 addr 0
+A _HEADER1 size 2 flags 8 addr 8
+A _HEADER2 size 2 flags 8 addr 10
+A _HEADER3 size 2 flags 8 addr 18
+A _HEADER4 size 2 flags 8 addr 20
+A _HEADER5 size 2 flags 8 addr 28
+A _HEADER6 size 2 flags 8 addr 30
+A _HEADER7 size 2 flags 8 addr 38
+A _HEADER8 size C flags 8 addr 100
+A _HOME size 0 flags 0 addr 0
+A _INITIALIZER size 0 flags 0 addr 0
+A _GSINIT size 6 flags 0 addr 0
+S gsinit Def0000
+A _GSFINAL size 1 flags 0 addr 0
+A _DATA size 0 flags 0 addr 0
+A _INITIALIZED size 0 flags 0 addr 0
+A _BSEG size 0 flags 0 addr 0
+A _BSS size 0 flags 0 addr 0
+A _HEAP size 0 flags 0 addr 0
+T 00 00
+R 00 00 02 00
+T 00 00 C3 00 01
+R 00 00 02 00 00 03 0A 00
+T 08 00
+R 00 00 03 00
+T 08 00 ED 4D
+R 00 00 03 00
+T 10 00
+R 00 00 04 00
+T 10 00 ED 4D
+R 00 00 04 00
+T 18 00
+R 00 00 05 00
+T 18 00 ED 4D
+R 00 00 05 00
+T 20 00
+R 00 00 06 00
+T 20 00 ED 4D
+R 00 00 06 00
+T 28 00
+R 00 00 07 00
+T 28 00 ED 4D
+R 00 00 07 00
+T 30 00
+R 00 00 08 00
+T 30 00 ED 4D
+R 00 00 08 00
+T 38 00
+R 00 00 09 00
+T 38 00 ED 4D
+R 00 00 09 00
+T 00 01
+R 00 00 0A 00
+T 00 01
+R 00 00 0A 00
+T 00 01 31 FF FF CD 00 00 CD 00 00 C3 04 00
+R 00 00 0A 00 00 06 0D 00 02 09 00 00 00 0C 00 00
+T 00 00
+R 00 00 00 00
+T 00 00 3E 02 CF C9
+R 00 00 00 00
+T 04 00
+R 00 00 00 00
+T 04 00 3E 00 CF
+R 00 00 00 00
+T 07 00
+R 00 00 00 00
+T 07 00 76 18 FD
+R 00 00 00 00
+T 00 00
+R 00 00 0D 00
+T 00 00 78 B1 28 02 ED B0
+R 00 00 0D 00
+T 06 00
+R 00 00 0D 00
+T 00 00 C9
+R 00 00 0E 00
diff --git a/sw/z80_test/crt0.s b/sw/z80_test/crt0.s
index 00c7da1..7701ca6 100644
--- a/sw/z80_test/crt0.s
+++ b/sw/z80_test/crt0.s
@@ -27,7 +27,7 @@
;--------------------------------------------------------------------------
.module crt0
- .globl _kmain
+ .globl _main
.area _HEADER (ABS)
;; Reset vector
@@ -56,7 +56,7 @@ init:
;; Initialise global variables
call gsinit
- call _kmain
+ call _main
jp _exit
;; Ordering of segments for the linker.
diff --git a/sw/z80_test/ctc.c b/sw/z80_test/ctc.c
new file mode 100644
index 0000000..3a4e7d5
--- /dev/null
+++ b/sw/z80_test/ctc.c
@@ -0,0 +1,7 @@
+#include "ctc.h"
+
+void ctc_control()
+{
+
+}
+
diff --git a/sw/z80_test/ctc.h b/sw/z80_test/ctc.h
new file mode 100644
index 0000000..c6b3150
--- /dev/null
+++ b/sw/z80_test/ctc.h
@@ -0,0 +1,6 @@
+#ifndef __CTC_H__
+#define __CTC_H__
+
+void ctc_control();
+
+#endif /* __CTC_H__ */ \ No newline at end of file
diff --git a/sw/z80_test/devices.h b/sw/z80_test/devices.h
new file mode 100644
index 0000000..a846f9b
--- /dev/null
+++ b/sw/z80_test/devices.h
@@ -0,0 +1,15 @@
+#ifndef __DEVICES_H__
+#define __DEVICES_H__
+
+#define ADDR_DEV_ROM_L 0x0000
+#define ADDR_DEV_ROM_H 0x2000
+
+#define ADDR_DEV_USART 0x4000
+#define ADDR_DEV_CTC 0x4100
+#define ADDR_DEV_PIO 0x4200
+
+#define ADDR_DEV_MMU
+
+#define ADDR_DEV_RAM 0x8000
+
+#endif
diff --git a/sw/z80_test/main.c b/sw/z80_test/main.c
new file mode 100644
index 0000000..a90cd92
--- /dev/null
+++ b/sw/z80_test/main.c
@@ -0,0 +1,7 @@
+#include "usart.h"
+
+void main(void)
+{
+ usart_init(USART_BAUDRATE_9600, USART_PARITY_EVEN, USART_STOP_BITS_1);
+ usart_write("Hello, World!", 13);
+}
diff --git a/sw/z80_test/makefile b/sw/z80_test/makefile
index c709d61..f718044 100644
--- a/sw/z80_test/makefile
+++ b/sw/z80_test/makefile
@@ -1,11 +1,9 @@
####
# source code settings
#
-OSNAME := helvetiOS_test
+OSNAME := sample
-CSOURCES := $(wildcard kernel/*.c) \
- $(wildcard kernel/drivers/*.c) \
- $(wildcard libc/*.c)
+CSOURCES := $(wildcard *.c)
OBJECTS := $(patsubst %.c,build/%.rel,$(CSOURCES))
HEXFILE := build/$(OSNAME).hex
@@ -17,9 +15,7 @@ BINARY := build/$(OSNAME).bin
CC := sdcc
CFLAGS := -mz80 \
- -I kernel/include \
- -I kernel/include/drivers \
- -I libc/include \
+ -I . \
-DDEBUG
LDFLAGS := -mz80 --no-std-crt0 crt0.rel \
@@ -43,7 +39,7 @@ crt0.rel: crt0.s
sdasz80 -o $<
dirs:
- mkdir -p build build/kernel build/libc
+ mkdir -p build
dis: $(BINARY)
@# z80dasm -a -l -g 0h $< -o build/$(OSNAME).s
diff --git a/sw/z80_test/pio.c b/sw/z80_test/pio.c
new file mode 100644
index 0000000..5ca9149
--- /dev/null
+++ b/sw/z80_test/pio.c
@@ -0,0 +1,40 @@
+#include "pio.h"
+
+static uint8_t *pio_port = (uint8_t *) ADDR_DEV_PIO;
+static uint8_t *pio_ctrl = (uint8_t *) (ADDR_DEV_PIO + 2);
+
+inline void _pio_data(int port, uint8_t data)
+{
+ *(pio_port + port) = data;
+}
+
+inline void _pio_control(int port, uint8_t cmd)
+{
+ *(pio_ctrl + port) = cmd;
+}
+
+void pio_set_mode(int port, int mode, uint8_t io)
+{
+ // 0x0F is a control sequence to set mode
+ _pio_control(port, ((mode << 6) | 0x0F));
+
+ // this mode requires an additional argument that sets
+ // a mode for each pin
+ if (mode == PIO_MODE_BIT_IO) {
+ _pio_control(port, io);
+ }
+}
+
+void pio_set_interrupts(int port, int control)
+{
+ // 0x07 is a control sequence to set interrupts
+ _pio_control(port, (control | 0x07));
+}
+
+void pio_set_interrupts_mask(int port, int control, uint8_t mask)
+{
+ // 0x17 is a control sequence to set interrupts
+ // and to interpret the next byte as a mask
+ _pio_control(port, (control | 0x17));
+ _pio_control(port, mask);
+}
diff --git a/sw/z80_test/pio.h b/sw/z80_test/pio.h
new file mode 100644
index 0000000..0df2ed0
--- /dev/null
+++ b/sw/z80_test/pio.h
@@ -0,0 +1,37 @@
+#ifndef __PIO_H__
+#define __PIO_H__
+
+#include "devices.h"
+#include "types.h"
+
+#define PIO_A 0
+#define PIO_B 1
+
+#define PIO_MODE_BYTE_IN 0
+#define PIO_MODE_BYTE_OUT 1
+#define PIO_MODE_BYTE_BI 2
+#define PIO_MODE_BIT_IO 3
+
+#define PIO_INT_ACTIVE_HIGH (1<<5)
+#define PIO_INT_AND_MODE (1<<6)
+#define PIO_INT_ENABLE (1<<7)
+
+
+inline void _pio_data(int port, uint8_t data);
+inline void _pio_control(int port, uint8_t cmd);
+
+void pio_set_mode(int port, int mode, uint8_t io);
+
+void pio_set_interrupts(int port, int control);
+void pio_set_interrupts_mask(int port, int control, uint8_t mask);
+
+// uint8_t pio_read_data(int port);
+uint8_t pio_read(int port);
+void pio_write(int port, uint8_t data);
+
+inline int pio_read_pin(int port, uint8_t pin);
+inline void pio_write_pin(int port, uint8_t pin);
+
+// TODO: implement mode (in/out/both) and interrupt vector
+
+#endif // __PIO_H__
diff --git a/sw/z80_test/types.h b/sw/z80_test/types.h
new file mode 100644
index 0000000..815fc68
--- /dev/null
+++ b/sw/z80_test/types.h
@@ -0,0 +1,13 @@
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+/* only types from primitive types are defined in this file */
+
+typedef volatile unsigned char register_t;
+
+typedef unsigned int uint;
+typedef char int8_t;
+typedef unsigned char uint8_t;
+typedef int int16_t;
+typedef unsigned int uint16_t;
+#endif
diff --git a/sw/z80_test/usart.c b/sw/z80_test/usart.c
new file mode 100644
index 0000000..9ec6dbd
--- /dev/null
+++ b/sw/z80_test/usart.c
@@ -0,0 +1,91 @@
+#include "usart.h"
+
+static struct _usart_device *_usart = (struct _usart_device *) ADDR_DEV_USART;
+
+void usart_set_baudrate(uint16_t baudrate)
+{
+ // enable latch access
+ _usart->LCR.divisor_latch_access = 1;
+ _usart->buffer = 0x00FF & baudrate; // LSBs
+ memcpy(&_usart->IER, &(baudrate >>8), 1);
+ // _usart->IER = 0x00FF & (baudrate >> 8); // MSBs
+ _usart->LCR.divisor_latch_access = 0;
+}
+
+void usart_set_parity(int mode)
+{
+ if (mode == USART_PARITY_EVEN) {
+ _usart->LCR.even_parity = 1;
+ }
+ else if (mode == USART_PARITY_ODD) {
+ _usart->LCR.even_parity = 0;
+ }
+
+ _usart->LCR.parity = (mode == USART_PARITY_NONE) ? 0 : 1;
+}
+
+void usart_set_stop_bits(int count)
+{
+ _usart->LCR.stop_bits = (count == USART_STOP_BITS_1) ? 0 : 1;
+}
+
+void usart_word_length(int length)
+{
+ _usart->LCR.word_length = length;
+}
+
+void usart_set_autoflow(int mode)
+{
+ _usart->MCR.autoflow = (mode == USART_AUTOFLOW_OFF) ? 0 : 1;
+ _usart->MCR.data_terminal_ready = (mode == USART_AUTOFLOW_ALL);
+}
+
+inline void usart_init(uint16_t baudrate, int parity, int stop_bits)
+{
+ usart_set_baudrate(baudrate);
+ usart_set_parity(parity);
+ usart_set_stop_bits(stop_bits);
+ usart_set_autoflow(USART_AUTOFLOW_OFF);
+}
+
+void usart_transmit(uint8_t data)
+{
+ _usart->buffer = data;
+ while (_usart->LSR.transmitter_holder_empty == 0); // wait
+}
+
+uint8_t usart_receive()
+{
+ return _usart->buffer;
+}
+
+int usart_write(uint8_t *data, size_t size)
+{
+ uint8_t *dp = data;
+
+ while (size--) {
+ _usart->buffer = *(dp++);
+ while (_usart->LSR.transmitter_empty);
+ }
+
+ // TODO: do something that actually counts for sent bytes
+ return size;
+}
+
+int usart_read(uint8_t *buffer, size_t count)
+{
+ uint8_t *bp = buffer;
+ size_t read_count = 0;
+
+ while (count--) {
+ *(bp++) = _usart->buffer;
+ // check for errors
+ if (_usart->LSR.framing_error || _usart->LSR.parity_error) {
+ bp--; // delete last byte (?)
+ } else {
+ read_count++;
+ }
+ }
+
+ return read_count;
+}
diff --git a/sw/z80_test/usart.h b/sw/z80_test/usart.h
new file mode 100644
index 0000000..b85ee3e
--- /dev/null
+++ b/sw/z80_test/usart.h
@@ -0,0 +1,155 @@
+#ifndef __USART_H__
+#define __USART_H__
+
+#include "types.h"
+#include "devices.h"
+
+#include "string.h"
+
+// baudrate clock divisors
+// values from TL16C550C datasheet (table 9 for 1.8432 MHz crystal)
+#define USART_BAUDRATE_50 2304
+#define USART_BAUDRATE_75 1536
+#define USART_BAUDRATE_110 1047
+#define USART_BAUDRATE_134_5 857
+#define USART_BAUDRATE_150 768
+#define USART_BAUDRATE_300 384
+#define USART_BAUDRATE_600 192
+#define USART_BAUDRATE_1200 96
+#define USART_BAUDRATE_1800 64
+#define USART_BAUDRATE_2000 58
+#define USART_BAUDRATE_2400 48
+#define USART_BAUDRATE_3600 32
+#define USART_BAUDRATE_4800 24
+#define USART_BAUDRATE_7200 16
+#define USART_BAUDRATE_9600 12
+#define USART_BAUDRATE_19200 6
+#define USART_BAUDRATE_38400 3
+#define USART_BAUDRATE_56000 3
+
+// parity
+#define USART_PARITY_NONE 0
+#define USART_PARITY_EVEN 1
+#define USART_PARITY_ODD 2
+
+// stop bits
+#define USART_STOP_BITS_1 10
+#define USART_STOP_BITS_15 15
+#define USART_STOP_BITS_2 20
+
+// word lenght
+#define USART_WORD_LENGTH_5 0
+#define USART_WORD_LENGTH_6 1
+#define USART_WORD_LENGTH_7 2
+#define USART_WORD_LENGTH_8 3
+
+// autoflow
+#define USART_AUTOFLOW_ALL 3
+#define USART_AUTOFLOW_CTS 2
+#define USART_AUTOFLOW_OFF 0
+
+/* stuctures for usart registers */
+struct IER
+{
+ volatile uint received_data_interrupt :1;
+ volatile uint transmitter_empty_interrupt :1;
+ volatile uint receiver_line_status_interrupt :1;
+ volatile uint modem_status_interrupt :1;
+ volatile uint reserved :4;
+};
+
+struct IIR
+{
+ volatile uint interrupt_pending :1;
+ volatile uint interrupt_id :3;
+ volatile uint reserved :2;
+ volatile uint fifos :2;
+};
+
+struct FCR
+{
+ volatile uint fifo_enable :1;
+ volatile uint receiver_fifo_rst :1;
+ volatile uint trasmitter_fifo_rst :1;
+ volatile uint dma_mode_select :1;
+ volatile uint reserved :1;
+ volatile uint receiver_trigger :2;
+};
+
+struct LCR
+{
+ volatile uint word_length :2;
+ volatile uint stop_bits :1;
+ volatile uint parity :1;
+ volatile uint even_parity :1;
+ volatile uint stick_parity :1;
+ volatile uint break_control :1;
+ volatile uint divisor_latch_access :1;
+};
+
+struct MCR
+{
+ volatile uint data_terminal_ready :1;
+ volatile uint request_to_send :1;
+ volatile uint out1;
+ volatile uint out2;
+ volatile uint loop;
+ volatile uint autoflow :1;
+ volatile uint reserved :2;
+};
+
+struct LSR
+{
+ volatile uint data_ready :1;
+ volatile uint overrun_error :1;
+ volatile uint parity_error :1;
+ volatile uint framing_error :1;
+ volatile uint break_interrupt :1;
+ volatile uint transmitter_holder_empty :1;
+ volatile uint transmitter_empty :1;
+ volatile uint fifo_recv_error :1;
+};
+
+struct MSR
+{
+ volatile uint delta_cts :1;
+ volatile uint delta_data_set_ready :1;
+ volatile uint trailing_edge_ring_indicator :1;
+ volatile uint delta_data_carrier_detect :1;
+ volatile uint clear_to_send :1;
+ volatile uint data_set_ready :1;
+ volatile uint ring_indicator :1;
+ volatile uint data_carrier_detect :1;
+};
+
+/* this structure is only for internal usage */
+struct _usart_device
+{
+ register_t buffer; // also used as LSB for divisor latch
+ struct IER IER;
+ struct IIR IIR;
+ struct FCR FCR;
+ struct LCR LCR;
+ struct MCR MCR;
+ struct LSR LSR;
+ struct MSR MSR;
+ register_t scratch;
+};
+
+
+// setup functions (wrappers)
+void usart_set_baudrate(uint16_t baudrate);
+void usart_set_parity(int mode);
+void usart_set_stop_bits(int count);
+void usart_set_word_length(int length);
+void usart_set_autoflow(int mode);
+
+inline void usart_init(uint16_t baudrate, int parity, int stop_bits);
+
+void usart_transmit(uint8_t data);
+uint8_t usart_receive();
+
+int usart_write(uint8_t *data, size_t size);
+int usart_read(uint8_t *buffer, size_t count);
+
+#endif // __USART__H__