Beispiel #1
0
/*
	Check whether instruction fetch is allowed at adr.
	The returned value can be used by breakpoints to determine the
	origin of violation.
*/
int hwp_fetch(uint32_t adr)
{
	// protections (hw1)
	if(tihw.hw_type == HW1)
	{
		if(IN_BOUNDS2(0x390000+tihw.archive_limit*0x10000, 
								adr, 0x3fffff))				// archive memory limit (hw1)
		{
			// three consecutive access to any adress >=$390000+limit*$10000 and <$400000 crashes the calc
			if(!(adr & 1)) arch_mem_crash++;
			if((tihw.hw_type == HW1) && (arch_mem_crash >= 4))
			{
				freeze_calc();
				return 1;
			}
		}
	}

	// protections (hw2)
	else
	{
		if(IN_BOUNDS(0x000000, adr, 0x03ffff))				// RAM page execution protection
		{
			if(tihw.ram_exec[adr >> 12]) 
			{
				freeze_calc();
				return 2;
			}
		}
		else if(IN_BOUNDS(0x040000, adr, 0x1fffff))			// RAM page execution protection
		{
			if(io2_bit_tst(6, 7)) 
			{
				freeze_calc();
				return 2;
			}
		}
		else if(IN_BOUNDS2(0x210000, adr, 0x1fffff + tihw.rom_size))	// FLASH page execution protection
		{
			if(adr >= (0x210000+ba + (uint32_t)tihw.io2[0x13]*0x10000)) 
			{
				//printf(">> $%06x-%06x ", adr, 0x210000+ba + (uint32_t)tihw.io2[0x13]*0x10000);
				freeze_calc();
				return 3;
			}
		}
	}
Beispiel #2
0
/*
    This function is called by do_cycles to regularly updates the hardware.
    Rate is the same as the timer tick rate.
*/
void hw_update(void)
{
	static unsigned int timer;
	//time_t curr_clock;

	// OSC2 enable (bit clear means oscillator stopped!)
	int osc2_enabled = io_bit_tst(0x15,1);

	timer++;
	if (osc2_enabled)
	{
		// Increment timer
		if(!(timer & timer_mask) && io_bit_tst(0x15,3))
		{
			if (tihw.timer_value == 0x00) 
				tihw.timer_value = tihw.io[0x17];
			else 
				tihw.timer_value++;
		}
	}

	// Increment HW2 RTC timer every 8192 seconds
	if ((tihw.hw_type >= HW2) && io2_bit_tst(0x1f, 2) && io2_bit_tst(0x1f, 1))
	{
		static struct timeval ref = {0, 0};
		struct timeval tmp = {0, 0};
		gettimeofday(&tmp, NULL);

		// Check if 8192 seconds elapsed, avoiding 32-bit overflow
		if((unsigned)(tmp.tv_sec-ref.tv_sec)*500000u
		   + ((unsigned)(tmp.tv_usec-ref.tv_usec)>>1u) >= 4096000000u)
		{
			gettimeofday(&ref, NULL);
			tihw.rtc_value++;
		}
	}

	// Toggles every FS (every time the LCD restarts at line 0) -> 90 Hz ~ timer/192
	// Don't use the actual LCD count (and use 192 rather than 182) to keep exposure
	// times consistent
	if(!(timer % 192) && tihw.hw_type >= HW2) 
		tihw.io2[0x1d] ^= 0x80;

	/* Auto-int management */

	if (osc2_enabled)
	{
		// Auto-int 1: 1/2^6 of timer rate
		// Triggered at a fixed rate: OSC2/2^11 = (OSC2/2^5)/2^6
		if(!(timer & 63)) 
		{
			if(!io_bit_tst(0x15,7))
				if((tihw.hw_type == HW1) || !(io2_bit_tst(0x1f, 2) && !io2_bit_tst(0x1f, 1)))
					hw_m68k_irq(1);
		}

		// Auto-int 2: keyboard scan
		// see keyboard.c
	}

	if(osc2_enabled || tihw.hw_type == HW2)
	{
		// Auto-int 3: disabled by default by AMS
		// When enabled, it is triggered at a fixed rate: OSC2/2^19 = 1/16384 of timer rate = 1Hz
		if(!(timer & 16383))
		{
			if(!io_bit_tst(0x15,7) && io_bit_tst(0x15,2))
				if((tihw.hw_type == HW1) || !(io2_bit_tst(0x1f, 2) && !io2_bit_tst(0x1f, 1)))
					hw_m68k_irq(3);
		}
	}

	// DBus: External link activity ?
	/*
	if(!ticables_cable_get_d0(cable_handle) || !ticables_cable_get_d1(cable_handle))
	{
		io_bit_set(0x0d,3);	//SA
		io_bit_set(0x0d,2);	//EA
	}
	*/

	// DBUS enabled ?
	if(!io_bit_tst(0x0c,6))
	{
		// Check for data arrival (link cable)
		hw_dbus_checkread();

		// Auto-int 4: triggered by linkport (error, link act, txbuf empty or rxbuf full)
		if((io_bit_tst(0x0c,3) && io_bit_tst(0x0d,7))  ||
			(io_bit_tst(0x0c,2) && io_bit_tst(0x0d,3)) ||
			(io_bit_tst(0x0c,1) && io_bit_tst(0x0d,6)) ||
			(io_bit_tst(0x0c,0) && io_bit_tst(0x0d,5)))
		{
			hw_m68k_irq(4);
		}
	}

	if (osc2_enabled)
	{
		// Auto-int 5: triggered by the programmable timer.
		// The default rate is OSC2/(K*2^9), where K=79 for HW1 and K=53 for HW2
		// Make sure AI5 is triggered only if the timer was actually incremented.
		if(!(timer & timer_mask) && io_bit_tst(0x15,3) && tihw.timer_value == 0)
		{
			if(!io_bit_tst(0x15,7))	
				if((tihw.hw_type == HW1) || !(io2_bit_tst(0x1f, 2) && !io2_bit_tst(0x1f, 1)))
					hw_m68k_irq(5);
		}
	}

	// Auto-int 6: triggered when [ON] is pressed.
	// see keyboard.c

	// Auto-int 7: "vector table write protection" & "stack overflow"
	// see memory.c

	/* Hardware refresh */
  
	// Update keyboard (~600Hz). Not related to timer but as a convenience
	if(!(timer & 127))	// 31 and 63 don't work, 127 and 255 are ok
		hw_kbd_update();

	// Update LCD (HW1: every 256th timer tick, HW2: unrelated)
	if((tihw.hw_type == HW1) && !(timer & 255))
	{
		G_LOCK(lcd_flag);
		lcd_flag = !0;
		G_UNLOCK(lcd_flag);
		lcd_hook_hw1();
	}
}
Beispiel #3
0
void io_put_byte(uint32_t addr, uint8_t arg)
{
	addr &= 31;	//tihw.io_size-1;

    switch(addr) 
    {
        case 0x00:	// rw <76...2..>
			// %5: bit 0 of contrast (TI92)
			if(tihw.calc_type == TI92)
                bit_chg(tihw.contrast,0,bit_get(arg,5));
        break;
        case 0x01:	// rw <.....2.0>
			// %0 clr: interleave RAM (allows use of 256K of RAM)
            if(tihw.hw_type == 1)
				tihw.ram_size = bit_tst(arg, 0) ? 128*KB : 256*KB;

			// %2 set: protected memory violation triggered when memory below [$000120] is written
	    break;
	    case 0x02:	// ??
	    break;
		case 0x03:	// -w <.654.210>
			// Bus waitstates
			break;
        case 0x04:
        break;
        case 0x05:	// -w <...43210>
			// turn off OSC1 (CPU), wake on int level 6 (ON key) and int level [5..1]
			m68k_setstopped(1);
        break;
        case 0x06: 
		case 0x07: 
		case 0x08: 
		case 0x09: 
		case 0x0a: 
		case 0x0b:
        break;
        case 0x0c:	// rw <765.3210>
        	// %[3:0]: Trigger interrupt level 4 on error, activity, tx empty, rx full
        	// see hardware.c
			// %6: link disable (usually reset link port or direct access to wires)
			if(bit_get(arg, 6))
				hw_dbus_reset();
        break;
        case 0x0d:	// r- <76543210>
			break;
        case 0x0e:	// rw <....3210>
			// set red/white wires (if direct access)			
			if(io_bit_tst(0x0c,6))
	        {
	            lc.set_red_wire(!bit_get(arg,0));
	            lc.set_white_wire(!bit_get(arg,1));
	        }
        break;
        case 0x0f: 	// rw <76543210>
			// write a byte to the transmit buffer (1 byte buffer)
			io_bit_clr(0x0d, 0);	// STX=0 (tx reg is full)
            hw_dbus_putbyte(arg);
            break;
        case 0x10: 	// -w <76543210> (hw1)
			// address of LCD memory divided by 8 (msb)
			if(tihw.hw_type == HW1)
				tihw.lcd_adr = ((arg << 8) | tihw.io[0x11]) << 3;
        break;
        case 0x11: 	// -w <76543210> (hw1)
			// address of LCD memory divided by 8 (lsb)
			if(tihw.hw_type == HW1)
				tihw.lcd_adr = ((tihw.io[0x10] << 8) | arg) << 3;
        break;
        case 0x12:	// -w <76543210>
			// LCD logical width = (64-n)*2 bytes = (64-n)*16 pixels <=> n = 64-w/16
			tihw.log_w = (64 - arg) * 16;
        break;
        case 0x13:	// -w <..543210>
			// LCD logical height = (256-n) <=> n = 256-h
			tihw.log_h = 0x100 - arg;
        break;
        case 0x14:
        break;
        case 0x15:	// rw <7.6543210>
        	// %7 set: Master disable timer interrupts (level 1, 3 and 5)
        	// see hardware.c
        	
        	// %[5-4]: Increment rate of $600017 (prescaler)
			set_prescaler((arg >> 4) & 3);
        	
        	// %3 set: Enable incrementing of $600017
        	// see hardware.c        	
        	
        	// %2 set: Trigger interrupt level 3 at OSC2/2^19  (~1 Hz on HW2)
        	// see hardware.c
        	
        	// %1 set: OSC2 (and OSC3?) enable (bit clear means oscillator stopped!)
        	// see hardware.c
        	
        	// %0 set: LCD controller DMA enable else LCD blank ("white")
        	// could be implemented but redundant with tihw.on_off
        break;
        case 0x16:
        break;
        case 0x17: 	// rw <76543210>
			// programmable rate generator
            break;
        case 0x18:	// rw <......10>
			// keyboard row mask (see keyboard.c)
        break;    
        case 0x19:	// rw <76543210>
			// keyboard row mask (see keyboard.c)
        break;
        case 0x1a:	// r- <......10>
        	// ON key status (see keyboard.c)
        	// Write any value to $60001A to acknowledge this interrupt (AutoInt6)
        break;
        case 0x1b:	// r- <76543210>
			// keyboard column status (see keyboard.c)
        	// Write any value to $60001B to acknowledge this interrupt (AutoInt2)
        break;
        case 0x1c:	// -w <..5432..>
        	// %[5-2] set: LCD RS (row sync) frequency, OSC2/((16-n)*8)
        	// %1111 turns off the RS completely (used when LCD is off)        	
			tihw.on_off = ((arg & 0x3c) == 0x3c) ? 0 : 1;
        break;
        case 0x1d:	// -w <7..43210>
			// %[3-0]: contrast
			if(tihw.calc_type == TI92)
			{
				// %[3-0]: bits <4321.> of contrast
				static int avg = 0;				

				avg = (avg + arg)/2;	// filter value
            	tihw.contrast = (tihw.contrast & 1) | ((avg & 15) << 1);
            }
            else
            {
            	// %[4/3-0]: LCD contrast bits 4/3-0 (bit 4/3 is msb on HW2/HW1)
				tihw.contrast = arg & (io2_bit_tst(0x1f,0) ? 0x1f : 0x0f);
				
				if(tihw.calc_type == TI89 || tihw.calc_type == TI89t)
				{
					if(tihw.hw_type == HW1)
            			tihw.contrast = 31 - 2*tihw.contrast;
					else
						tihw.contrast = 31 - tihw.contrast;
				}
            }
        break;
        case 0x1e:
        break;
        case 0x1f:
        break;
    }
  
    tihw.io[addr] = arg;
}