summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/f8/f3853.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/f8/f3853.c')
-rw-r--r--src/emu/cpu/f8/f3853.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/emu/cpu/f8/f3853.c b/src/emu/cpu/f8/f3853.c
new file mode 100644
index 00000000000..4aa0d9dc908
--- /dev/null
+++ b/src/emu/cpu/f8/f3853.c
@@ -0,0 +1,152 @@
+/*
+ fairchild f3853 smi static ram interface
+ with integrated interrupt controller and timer
+
+ databook found at www.freetradezone.com
+*/
+
+#include "f3853.h"
+
+/*
+ the smi does not have DC0 and DC1, only DC0
+ it is not reacting to the cpus DC0/DC1 swap instruction
+ --> might lead to 2 devices having reacting to the same DC0 address
+ and placing their bytes to the databus!
+*/
+
+/*
+ 8 bit shift register
+ feedback in0 = not ( (out3 xor out4) xor (out5 xor out7) )
+ interrupt at 0xfe
+ 0xff stops register (0xfe never reached!)
+*/
+static UINT8 f3853_value_to_cycle[0x100];
+
+static struct {
+ F3853_CONFIG config;
+
+ UINT8 high,low; // bit 7 set to 0 for timer interrupt, to 1 for external interrupt
+ int external_enable;
+ int timer_enable;
+
+ int request_flipflop;
+
+ int priority_line; /* inverted level*/
+ int external_interrupt_line;/* inverted level */
+
+ emu_timer *timer;
+} f3853= { { 0 } };
+#define INTERRUPT_VECTOR(external) (external?f3853.low|(f3853.high<<8)|0x80 \
+ :(f3853.low|(f3853.high<<8))&~0x80)
+
+static void f3853_set_interrupt_request_line(void)
+{
+ if (!f3853.config.interrupt_request)
+ return;
+
+ if (f3853.external_enable&&!f3853.priority_line)
+ f3853.config.interrupt_request(INTERRUPT_VECTOR(TRUE), TRUE);
+ else if (f3853.timer_enable&&!f3853.priority_line&&f3853.request_flipflop)
+ f3853.config.interrupt_request(INTERRUPT_VECTOR(FALSE), TRUE);
+ else
+ f3853.config.interrupt_request(0, FALSE);
+}
+
+static TIMER_CALLBACK( f3853_timer_callback );
+
+static void f3853_timer_start(UINT8 value)
+{
+ attotime period = (value != 0xff) ? attotime_mul(ATTOTIME_IN_HZ(f3853.config.frequency), f3853_value_to_cycle[value]*31) : attotime_never;
+
+ timer_adjust(f3853.timer, period, 0, attotime_never);
+}
+
+static TIMER_CALLBACK( f3853_timer_callback )
+{
+ if (f3853.timer_enable)
+ {
+ f3853.request_flipflop = TRUE;
+ f3853_set_interrupt_request_line();
+ }
+ f3853_timer_start(0xfe);
+}
+
+
+void f3853_init(F3853_CONFIG *config)
+{
+ UINT8 reg=0xfe;
+ int i;
+
+ for (i=254/*known to get 0xfe after 255 cycles*/; i>=0; i--)
+ {
+ int o7=reg&0x80?TRUE:FALSE, o5=reg&0x20?TRUE:FALSE,
+ o4=reg&0x10?TRUE:FALSE, o3=reg&8?TRUE:FALSE;
+ f3853_value_to_cycle[reg]=i;
+ reg<<=1;
+ if (!((o7!=o5)!=(o4!=o3))) reg|=1;
+ }
+
+ f3853.config=*config;
+
+ f3853.priority_line=FALSE;
+ f3853.external_interrupt_line=TRUE;
+ f3853.timer = timer_alloc(f3853_timer_callback);
+}
+
+void f3853_reset(void)
+{
+ // registers indeterminate
+}
+
+void f3853_set_external_interrupt_in_line(int level)
+{
+ if (f3853.external_interrupt_line&&!level&& f3853.external_enable)
+ f3853.request_flipflop = TRUE;
+ f3853.external_interrupt_line = level;
+ f3853_set_interrupt_request_line();
+}
+
+void f3853_set_priority_in_line(int level)
+{
+ f3853.priority_line=level;
+ f3853_set_interrupt_request_line();
+}
+
+ READ8_HANDLER(f3853_r)
+{
+ UINT8 data=0;
+ switch (offset) {
+ case 0:
+ data=f3853.high;
+ break;
+ case 1:
+ data=f3853.low;
+ break;
+ case 2: // interrupt control; not readable
+ case 3: // timer; not readable
+ break;
+ }
+ return data;
+}
+
+WRITE8_HANDLER(f3853_w)
+{
+ switch (offset) {
+ case 0:
+ f3853.high=data;
+ break;
+ case 1:
+ f3853.low=data;
+ break;
+ case 2: //interrupt control
+ f3853.external_enable = ((data&3)==1);
+ f3853.timer_enable = ((data&3)==3);
+ f3853_set_interrupt_request_line();
+ break;
+ case 3: //timer
+ f3853.request_flipflop=FALSE;
+ f3853_set_interrupt_request_line();
+ f3853_timer_start(data);
+ break;
+ }
+}