From aff63a211e9b1e397adb9dce726d8153beb96dcd Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Wed, 30 Dec 2020 16:55:06 +0100 Subject: - 7seg is a subdevice of the VIA 6522 now, registering to a small sub-bus --- emu/6522.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ emu/6522.h | 46 ++++++++++++++++++++++++++++++++ emu/7seg.c | 48 +++++++++++++++------------------ emu/7seg.h | 14 +++++----- emu/CMakeLists.txt | 1 + emu/bus.c | 21 ++++++++++++--- emu/bus.h | 7 +++++ emu/device.h | 3 --- emu/emu.c | 9 +++++-- emu/emul.c | 9 ++++--- 10 files changed, 189 insertions(+), 47 deletions(-) create mode 100644 emu/6522.c create mode 100644 emu/6522.h 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 +#include + +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 +#include + +#ifdef WITH_GUI +#include +#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 #include +#ifdef WITH_GUI +#include +#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 +#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 @@ -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 ); -- cgit v1.2.3-54-g00ecf