summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-12-30 16:55:06 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2020-12-30 16:55:06 +0100
commitaff63a211e9b1e397adb9dce726d8153beb96dcd (patch)
tree28f5b85fde65cff328fad0ea1d24fe93e5678b2e
parent53569267c59204f56e4c0fddb669536d28706e5c (diff)
download6502-aff63a211e9b1e397adb9dce726d8153beb96dcd.tar.gz
6502-aff63a211e9b1e397adb9dce726d8153beb96dcd.tar.bz2
- 7seg is a subdevice of the VIA 6522 now, registering to
a small sub-bus
-rw-r--r--emu/6522.c78
-rw-r--r--emu/6522.h46
-rw-r--r--emu/7seg.c48
-rw-r--r--emu/7seg.h14
-rw-r--r--emu/CMakeLists.txt1
-rw-r--r--emu/bus.c21
-rw-r--r--emu/bus.h7
-rw-r--r--emu/device.h3
-rw-r--r--emu/emu.c9
-rw-r--r--emu/emul.c9
10 files changed, 189 insertions, 47 deletions
diff --git a/emu/6522.c b/emu/6522.c
new file mode 100644
index 0000000..df9144d
--- /dev/null
+++ b/emu/6522.c
@@ -0,0 +1,78 @@
+#include "6522.h"
+
+#include <stdio.h>
+#include <stdbool.h>
+
+static device_vtable_t const via_6522_vtable = {
+ via_6522_read,
+ via_6522_write,
+#ifdef WITH_GUI
+ via_6522_draw,
+#endif
+ via_6522_deinit
+};
+
+void via_6522_init( via_6522_t *via, uint16_t addr, bool initialize )
+{
+ device_init( &via->base, "via_6522" );
+ via->base.vtable = (device_vtable_t *)&via_6522_vtable;
+
+ via->addr = addr;
+ via->debug = false;
+
+ if( initialize ) {
+ via->ddra = 0x00;
+ }
+
+ bus_init( &via->bus );
+}
+
+void via_6522_register( via_6522_t *via, device_t *device )
+{
+ bus_register( &via->bus, device, 0, 0 );
+}
+
+uint8_t via_6522_read( void *obj, uint16_t addr )
+{
+ return 0;
+}
+
+void via_6522_write( void *obj, uint16_t addr, uint8_t data )
+{
+ via_6522_t *via = (via_6522_t *)obj;
+
+ switch( addr - via->addr ) {
+ case DDRA:
+ via->ddra = data;
+ break;
+
+ case PORTA:
+ data &= via->ddra;
+ for( int i = 0; i < via->bus.nof_devices; i++ ) {
+ device_t *device = via->bus.devices[i].device;
+ device->vtable->write( device, 0, data );
+ }
+ break;
+
+ default:
+ fprintf( stderr, "ERROR: VIA 6522 not implemented address '%04X', data: '%02X'\n", addr, data );
+ break;
+ }
+}
+
+#ifdef WITH_GUI
+void via_6522_draw( void *obj, SDL_Renderer *renderer )
+{
+ via_6522_t *via = (via_6522_t *)obj;
+
+ via->bus.base.vtable->draw( &via->bus, renderer );
+}
+#endif
+
+void via_6522_deinit( void *obj )
+{
+ via_6522_t *via = (via_6522_t *)obj;
+
+ bus_deinit( &via->bus );
+ device_deinit( &via->base );
+}
diff --git a/emu/6522.h b/emu/6522.h
new file mode 100644
index 0000000..853bd3e
--- /dev/null
+++ b/emu/6522.h
@@ -0,0 +1,46 @@
+#ifndef VIA_6522_H
+#define VIA_6522_H
+
+#include "device.h"
+#include "bus.h"
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef WITH_GUI
+#include <SDL.h>
+#endif
+
+// the VIA connects to sub-devices itself via the bus. It also
+// has things like timers and internal registers
+// the VIA is initialized with a base address, the addresses for
+// the registers are relative to this base.
+enum {
+ PORTA = 0x01,
+ DDRA = 0x03
+};
+
+typedef struct via_6522_t
+{
+ device_t base;
+
+ uint16_t addr;
+
+ uint8_t ddra;
+
+ bool debug;
+
+ bus_t bus;
+} via_6522_t;
+
+void via_6522_init( via_6522_t *via, uint16_t addr, bool initialize );
+void via_6522_register( via_6522_t *via, device_t *device );
+
+uint8_t via_6522_read( void *obj, uint16_t addr );
+void via_6522_write( void *obj, uint16_t addr, uint8_t data );
+#ifdef WITH_GUI
+void via_6522_draw( void *obj, SDL_Renderer *renderer );
+#endif
+void via_6522_deinit( void *obj );
+
+#endif
diff --git a/emu/7seg.c b/emu/7seg.c
index 787b280..d2b2d20 100644
--- a/emu/7seg.c
+++ b/emu/7seg.c
@@ -17,12 +17,11 @@ static device_vtable_t const seg7_vtable = {
seg7_deinit
};
-void seg7_init( seg7_t *seg, uint16_t addr, bool initialize )
+void seg7_init( seg7_t *seg, bool initialize )
{
device_init( &seg->base, "seg7" );
seg->base.vtable = (device_vtable_t *)&seg7_vtable;
- seg->addr = addr;
seg->debug = false;
if( initialize ) {
@@ -33,39 +32,34 @@ void seg7_init( seg7_t *seg, uint16_t addr, bool initialize )
uint8_t seg7_read( void *obj, uint16_t addr )
{
+ // device is a write-only device
return 0;
}
void seg7_write( void *obj, uint16_t addr, uint8_t data )
{
seg7_t *seg = (seg7_t *)obj;
+
+ // address is not relevant, PORTA is connected to our signals
+ // via a databus
- switch( addr - seg->addr ) {
- case DDRA:
- seg->ddr = data;
- break;
-
- case PORTA:
- // write bits from SER into shift register on positive SRCLK
- if( ( seg->ddr | ( SRCLK & SER ) ) && ( data & SRCLK ) ) {
- seg->shift = ( seg->shift << 1 ) | ( data & SER );
- if( seg->debug ) {
- fprintf( stderr, "7seg shifting data, data is now %02X\n", seg->shift );
- }
- }
-
- // copy shift to latch register on positive RCLK
- if( ( seg->ddr | RCLK ) && ( data & RCLK ) ) {
- seg->latch = seg->shift;
- if( seg->debug ) {
- fprintf( stderr, "7seg copying %02X from shift to latch\n", seg->latch );
- }
- }
-
- break;
-
- // ignore writes to other addresses
+ // write bits from SER into shift register on positive SRCLK
+ if( data & SRCLK ) {
+ seg->shift = ( seg->shift << 1 ) | ( data & SER );
+ if( seg->debug ) {
+ fprintf( stderr, "7seg shifting data, data is now %02X\n", seg->shift );
+ }
}
+
+ // copy shift to latch register on positive RCLK
+ if( data & RCLK ) {
+ seg->latch = seg->shift;
+ if( seg->debug ) {
+ fprintf( stderr, "7seg copying %02X from shift to latch\n", seg->latch );
+ }
+ }
+
+ // ignore writes to other addresses
}
#ifdef WITH_GUI
diff --git a/emu/7seg.h b/emu/7seg.h
index 0256f83..f6e1e98 100644
--- a/emu/7seg.h
+++ b/emu/7seg.h
@@ -6,6 +6,10 @@
#include <stdint.h>
#include <stdbool.h>
+#ifdef WITH_GUI
+#include <SDL.h>
+#endif
+
// VIA connected on PORTA to 3 wires leading to the 3 coupled 74HC595
// shift register which enable the ROM address lines to read the LED
// segment data (cells 0-15 contain the encoded 7 segments of 16 hexdigits)
@@ -16,9 +20,6 @@
// +---- RCLK
// +----- SRCLK
enum {
- PORTA = 0x01,
- DDRA = 0x03,
-
SER = 0x01,
RCLK = 0x02,
SRCLK = 0x04
@@ -27,17 +28,14 @@ enum {
typedef struct seg7_t
{
device_t base;
-
- uint16_t addr;
-
- uint8_t ddr;
+
uint16_t shift;
uint16_t latch;
bool debug;
} seg7_t;
-void seg7_init( seg7_t *seg, uint16_t addr, bool initialize );
+void seg7_init( seg7_t *seg, bool initialize );
uint8_t seg7_read( void *obj, uint16_t addr );
void seg7_write( void *obj, uint16_t addr, uint8_t data );
diff --git a/emu/CMakeLists.txt b/emu/CMakeLists.txt
index 6e13d00..5d8465c 100644
--- a/emu/CMakeLists.txt
+++ b/emu/CMakeLists.txt
@@ -25,6 +25,7 @@ set(SRC
bus.c
6502.c
memory.c
+ 6522.c
7seg.c
emul.c
)
diff --git a/emu/bus.c b/emu/bus.c
index 68ec972..33617c7 100644
--- a/emu/bus.c
+++ b/emu/bus.c
@@ -6,7 +6,9 @@
static device_vtable_t const bus_vtable = {
bus_read,
bus_write,
- device_draw,
+#ifdef WITH_GUI
+ bus_draw,
+#endif
bus_deinit
};
@@ -55,13 +57,26 @@ void bus_write( void *obj, uint16_t addr, uint8_t data )
for( int i = 0; i < bus->nof_devices; i++ ) {
registered_device_t *reg = &bus->devices[i];
if( reg->from <= addr && addr <= reg->to ) {
- return reg->device->vtable->write( reg->device, addr, data );
+ reg->device->vtable->write( reg->device, addr, data );
+ return;
}
}
- fprintf( stderr, "ERROR: illegal bus access writing from address %04X\n", addr );
+ fprintf( stderr, "ERROR: illegal bus access writing to address %04X\n", addr );
}
+#ifdef WITH_GUI
+void bus_draw( void *obj, SDL_Renderer *renderer )
+{
+ bus_t *bus = (bus_t *)obj;
+
+ for( int i = 0; i < bus->nof_devices; i++ ) {
+ device_t *device = bus->devices[i].device;
+ device->vtable->draw( device, renderer );
+ }
+}
+#endif
+
void bus_deinit( void *obj )
{
bus_t *bus = (bus_t *)obj;
diff --git a/emu/bus.h b/emu/bus.h
index c1866cb..e39caae 100644
--- a/emu/bus.h
+++ b/emu/bus.h
@@ -3,6 +3,10 @@
#include "device.h"
+#ifdef WITH_GUI
+#include <SDL.h>
+#endif
+
enum {
MAX_NOF_DEVICES = 5
};
@@ -24,6 +28,9 @@ void bus_register( bus_t *bus, device_t *device, uint16_t from, uint16_t to );
uint8_t bus_read( void *obj, uint16_t addr );
void bus_write( void *obj, uint16_t addr, uint8_t data );
+#ifdef WITH_GUI
+void bus_draw( void *obj, SDL_Renderer *renderer );
+#endif
void bus_deinit( void *obj );
#endif
diff --git a/emu/device.h b/emu/device.h
index 81a1dd4..32285ca 100644
--- a/emu/device.h
+++ b/emu/device.h
@@ -21,9 +21,6 @@ typedef struct device_vtable_t {
typedef struct device_t {
device_vtable_t const *vtable;
char *name;
-#ifdef WITH_GUI
- SDL_Renderer *renderer;
-#endif
} device_t;
void device_init( device_t *device, const char *name );
diff --git a/emu/emu.c b/emu/emu.c
index 421d4cc..590f93e 100644
--- a/emu/emu.c
+++ b/emu/emu.c
@@ -1,6 +1,7 @@
#include "emul.h"
#include "6502.h"
#include "memory.h"
+#include "6522.h"
#include "7seg.h"
#include <stdlib.h>
@@ -26,6 +27,7 @@ int main( int argc, char *argv[] )
bus_t bus;
memory_t rom;
memory_t ram;
+ via_6522_t via;
seg7_t seg7;
cpu_6502_t cpu;
@@ -47,8 +49,11 @@ int main( int argc, char *argv[] )
memory_init( &ram, MEMORY_RAM, RAM_START, RAM_SIZE, args_info.initialize_given );
bus_register( &bus, &ram.base, RAM_START, RAM_END );
- seg7_init( &seg7, VIA_START, args_info.initialize_given );
- bus_register( &bus, &seg7.base, VIA_START, VIA_END );
+ via_6522_init( &via, VIA_START, args_info.initialize_given );
+ bus_register( &bus, &via.base, VIA_START, VIA_END );
+
+ seg7_init( &seg7, args_info.initialize_given );
+ via_6522_register( &via, &seg7.base );
cpu_6502_init( &cpu, &bus, args_info.initialize_given );
if( args_info.debug_given ) {
diff --git a/emu/emul.c b/emu/emul.c
index 3ee60c0..ac4b64c 100644
--- a/emu/emul.c
+++ b/emu/emul.c
@@ -152,10 +152,11 @@ void emul_run( emul_t *emul, int nof_steps )
SDL_RenderCopy( emul->renderer, emul->background_texture, NULL, NULL );
- for( int i = 0; i < emul->bus->nof_devices; i++ ) {
- device_t *device = emul->bus->devices[i].device;
- device->vtable->draw( device, emul->renderer );
- }
+ emul->bus->base.vtable->draw( emul->bus, emul->renderer );
+ //~ for( int i = 0; i < emul->bus->nof_devices; i++ ) {
+ //~ device_t *device = emul->bus->devices[i].device;
+ //~ device->vtable->draw( device, emul->renderer );
+ //~ }
SDL_RenderPresent( emul->renderer );