+ zstate = RESET;
+ }
+
+ /* Timer 5 */
+ PRR1 &= ~_BV(PRTIM5);
+ OCR5A = F_CPU / 1024 / 10 - 1; /* Timer: 10Hz interval (OC4A) */
+ TCCR5B = (0b01<<WGM52)|(0b101<<CS40); /* CTC Mode, Prescaler 1024 */
+ TIMSK5 = _BV(OCIE5A); /* Enable oca interrupt */
+
+}
+
+
+zstate_t z80_bus_state(void)
+{
+ return zstate;
+}
+
+
+static void z80_busreq_hpulse(void)
+{
+ z80_dbus_set_in();
+ z80_addrbus_set_in();
+
+#if 0
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ Z80_O_BUSREQ = 1;
+ Z80_O_BUSREQ = 1; /* 2 AVR clock cycles */
+ Z80_O_BUSREQ = 0; /* 2 AVR clock cycles */
+ }
+#endif
+
+#if 1
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ Z80_O_BUSREQ = 1;
+
+ do {
+ if (Z80_I_BUSACK == 1) {
+ Z80_O_BUSREQ = 0;
+ break;
+ }
+ } while (1);
+ }
+#endif
+
+ if (zstate & ZST_ACQUIRED) {
+ timer = BUS_TO;
+ while (Z80_I_BUSACK == 1 && timer)
+ ;
+ if (Z80_I_BUSACK == 0)
+ z80_addrbus_set_out();
+ }
+}
+
+
+/*
+
+ + | | | | |
+ + State | RESET | RESET_AQRD | RUNNING | RUNNING_AQRD |
+ + | | | | |
+ + | 0 | 1 | 2 | 3 |
+Event + | | | | |
+----------------+---------------+---------------+---------------+---------------+
+ | | | | |
+Reset | 0 | 0 | 0 | 0 |
+ | | | | |
+ | | | | |
+Request | 1 | | 3 | |
+ | | | | |
+ | | | | |
+Release | | 0 | | 2 |
+ | | | | |
+ | | | | |
+Run | 2 | 3 | | |
+ | | | | |
+ | | | | |
+Restart | | | 2 | 3 |
+ | | | | |
+ | | | | |
+M_Cycle | | | | 3 |
+ | | | | |
+ | | | | |
+*/
+
+zstate_t z80_bus_cmd(bus_cmd_t cmd)
+{
+ switch (cmd) {
+
+ case Reset:
+ z80_dbus_set_in();
+ z80_addrbus_set_in();
+ z80_reset_active();
+ Z80_O_BUSREQ = 1;
+ timer = BUS_TO;
+ while (Z80_I_BUSACK == 0 && timer)
+ ;
+ zstate = RESET;
+ break;
+
+ case Request:
+ switch (zstate) {
+ case RESET:
+ Z80_O_BUSREQ = 0;
+ z80_reset_inactive();
+ timer = BUS_TO;
+ while (Z80_I_BUSACK == 1 && timer)
+ ;
+ if (Z80_I_BUSACK == 0) {
+ z80_addrbus_set_out();
+ zstate = RESET_AQRD;
+ } else {
+ z80_reset_active();
+ Z80_O_BUSREQ = 1;
+ }
+ break;
+
+ case RUNNING:
+ Z80_O_BUSREQ = 0;
+ timer = BUS_TO;
+ while (Z80_I_BUSACK == 1 && timer)
+ ;
+ if (Z80_I_BUSACK == 0) {
+ z80_addrbus_set_out();
+ zstate = RUNNING_AQRD;
+ } else {
+ Z80_O_BUSREQ = 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case Release:
+ switch (zstate) {
+ case RESET_AQRD:
+ z80_dbus_set_in();
+ z80_addrbus_set_in();
+ z80_reset_active();
+ Z80_O_BUSREQ = 1;
+ timer = BUS_TO;
+ while (Z80_I_BUSACK == 0 && timer)
+ ;
+ zstate = RESET;
+ break;
+ case RUNNING_AQRD:
+ z80_dbus_set_in();
+ z80_addrbus_set_in();
+ Z80_O_BUSREQ = 1;
+ timer = BUS_TO;
+ while (Z80_I_BUSACK == 0 && timer)
+ ;
+ zstate = RUNNING;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case Run:
+ switch (zstate) {
+ case RESET:
+ _delay_ms(20); /* TODO: */
+ z80_reset_inactive();
+ zstate = RUNNING;
+ break;
+
+ case RESET_AQRD:
+ z80_dbus_set_in();
+ z80_addrbus_set_in();
+ z80_reset_pulse();
+ z80_addrbus_set_out();
+ zstate = RUNNING_AQRD;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case Restart:
+ switch (zstate) {
+ case RUNNING:
+ case RUNNING_AQRD:
+ z80_reset_pulse();
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case M_Cycle:
+ switch (zstate) {
+ case RUNNING_AQRD:
+ z80_busreq_hpulse(); /* TODO: */
+ break;
+ default:
+ break;
+ }
+ }
+ return zstate;