/***************************************************************
 *  Alcuin: A HP48 emulator for Amiga Computers
 * 
 *  (C) 1995 Stephan Schupfer (schupfer@sbox.tu-graz.ac.at)
 *
 */

/*#define DEBUG_SHUTDOWN 1*/

#include <stdio.h>
#include <exec/types.h>

#include "A48.h"
#include "hp48.h"
#include "device.h"
#include "timer.h"
#include "romio.h"


static int	interrupt_called = 0;
extern unsigned long timer_set;

/******************************************************************/
void do_reset(void)
{
memset(saturn_mem,1,5);
}

/******************************************************************/
void do_unconfigure(void)
{
int i=5;
long conf=0;

while (i--) {
	conf <<= 4;
	conf |= saturn_C[i];
	}
for (i=0;i<5;i++)
	if (saturn_base[i] == conf) break;
if (i==5) return;
saturn_mem[i]=1;
saturn_base[i]=0;
saturn_size[i]=0;
}

/******************************************************************/
int get_identification(void)
{
static int chip_id[] = { 0x19, 0x03, 0x05, 0x07, 0x01, 0x0, 
                         0x19, 0xf4, 0xf6, 0xf8, 0xf2, 0x0 };
int i,id;

for (i = 0; i < 5; i++)
	if (saturn_mem[i]) break;
id=chip_id[(saturn_mem[i]==2) ? (i+6) : i];
for (i = 0; i < 3; i++) {
	saturn_C[i] = id & 0xf;
	id >>= 4;
	}
return 0;
}

/******************************************************************/
void do_interupt(void)
{
interrupt_called = 1;
  if (saturn_intenable) {
    push(saturn_PC);
    saturn_PC = 0xf;
    saturn_intenable = 0;
  }
}

/******************************************************************/
void do_kbd_int(void)
{
interrupt_called = 1;
if (saturn_intenable) {
	push(saturn_PC);
	saturn_PC = 0xf;
	saturn_intenable = 0;
	}
else saturn_int_pending = 1;
}

/******************************************************************/
void do_reset_interupt_system(void)
{
int i=9;

saturn_kbd_ien = 1;
while (i--) {
	if (saturn_keybuf[i]) {
		do_kbd_int();
		break;
		}
	}
}

/******************************************************************/
void do_shutdown(void)
{
int wake;
t1_t2_ticks ticks;

if (device.display_touched) {
	device.display_touched = 0;
	if (display_on) update_display();
	}
stop_timer(RUN_TIMER);
start_timer(IDLE_TIMER);
if (eqz_x(saturn_OUT)) {
#ifdef DEBUG_SHUTDOWN
    fprintf(stderr, "%.5lx: SHUTDN: PC = 0\n", saturn_PC);
#endif
	saturn_intenable = 1;
	saturn_int_pending = 0;
	}

#ifdef DEBUG_SHUTDOWN
  fprintf(stderr, "%.5lx:\tSHUTDN: Timer 1 Control = %x, Timer 1 = %d\n",
          saturn_PC, saturn_t1_ctrl, saturn_timer1);
  fprintf(stderr, "%.5lx:\tSHUTDN: Timer 2 Control = %x, Timer 2 = %ld\n",
          saturn_PC, saturn_t2_ctrl, saturn_timer2);
#endif
wake=0;
do {
	Delay(10);
	ticks = get_t1_t2();
	if (saturn_t2_ctrl & 0x01) saturn_timer2 = ticks.t2_ticks;
	saturn_timer1 = set_t1 - ticks.t1_ticks;
	interrupt_called = 0;
	if (GetEvent() && interrupt_called) wake=1;
	if (saturn_timer2 <= 0) {
		if (saturn_t2_ctrl & 0x04) wake = 1;
		if (saturn_t2_ctrl & 0x02) {
			wake = 1;
			saturn_t2_ctrl |= 0x08;
			do_interupt();
			}
		}
	if (saturn_timer1 < 0) {
		saturn_timer1 &= 0x0f;
		if (saturn_t1_ctrl & 0x04) wake = 1;
		if (saturn_t1_ctrl & 0x03) {
			wake = 1;
			saturn_t1_ctrl |= 0x08;
			do_interupt();
			}
		}
	if (!wake) {
		interrupt_called = 0;
		receive_char();
		wake=interrupt_called;
		}
	if (menu_reset) {
		menu_reset=0;
		wake=1;
		}
	} while (!wake);
stop_timer(IDLE_TIMER);
start_timer(RUN_TIMER);
}

/******************************************************************/
inline void mmu_read_con20 (long addr, word_20 *con20)
{
*con20=0;
read_nibble(addr+4,con20);
}

/******************************************************************/
