mirror of
https://github.com/UzixLS/famicom-dumper.git
synced 2025-07-19 07:21:16 +03:00
176 lines
3.8 KiB
C
176 lines
3.8 KiB
C
#include "defines.h"
|
|
#include <avr/io.h>
|
|
#include <util/delay.h>
|
|
#include <inttypes.h>
|
|
#include "jtag.h"
|
|
#include "jtag_commands.h"
|
|
|
|
static uint8_t jtag_current_command = 0;
|
|
static uint16_t jtag_pos = 0;
|
|
static uint32_t jtag_tck_delay_value = 0;
|
|
static uint32_t jtag_num_tck = 0;
|
|
static uint32_t jtag_usecs = 0;
|
|
static uint16_t jtag_multi_count = 0;
|
|
static uint16_t jtag_multi_pos = 0;
|
|
static uint16_t jtag_multi_multi = 0;
|
|
|
|
static void tck_delay(uint8_t tms, uint32_t num_tck, uint32_t usecs)
|
|
{
|
|
if (tms)
|
|
PORT |= (1<<TMS_PIN);
|
|
else
|
|
PORT &= ~(1<<TMS_PIN);
|
|
PORT |= 1<<TCK_PIN;
|
|
int i;
|
|
for (i = 0; i < num_tck; i++)
|
|
{
|
|
PORT ^= 1<<TCK_PIN;
|
|
//_delay_us(1);
|
|
PORT ^= 1<<TCK_PIN;
|
|
//_delay_us(1);
|
|
}
|
|
for (i = 0; i < usecs; i++)
|
|
_delay_us(1);
|
|
}
|
|
|
|
static uint8_t pulse_tck(int tms, int tdi, int tdo)
|
|
{
|
|
if (tms)
|
|
PORT |= (1<<TMS_PIN);
|
|
else
|
|
PORT &= ~(1<<TMS_PIN);
|
|
if (tdi >= 0)
|
|
{
|
|
if (tdi)
|
|
PORT |= (1<<TDI_PIN);
|
|
else
|
|
PORT &= ~(1<<TDI_PIN);
|
|
}
|
|
PORT &= ~(1<<TCK_PIN);
|
|
//_delay_us(1);
|
|
PORT |= 1<<TCK_PIN;
|
|
//_delay_us(1);
|
|
if (tdo < 0) return 1;
|
|
return ((PORT_PIN >> TDO_PIN) & 1) == tdo;
|
|
}
|
|
|
|
static int jtag_parse_byte(uint8_t data)
|
|
{
|
|
int i, tms, tdi, tdo;
|
|
switch (jtag_current_command)
|
|
{
|
|
case 0:
|
|
jtag_current_command = data;
|
|
jtag_pos = 0;
|
|
break;
|
|
|
|
case JTAG_PULSE_TCK_DELAY:
|
|
if (jtag_pos == 0)
|
|
{
|
|
jtag_num_tck = 0;
|
|
jtag_usecs = 0;
|
|
jtag_tck_delay_value = data;
|
|
} else {
|
|
if ((jtag_pos < 4) && (jtag_tck_delay_value & 0b10)) // num_tck
|
|
{
|
|
jtag_num_tck |= (uint32_t)data << (8*(jtag_pos-1));
|
|
} else if ((jtag_pos < 4) && !(jtag_tck_delay_value & 0b10)) // usecs
|
|
{
|
|
jtag_usecs |= (uint32_t)data << (8*(jtag_pos-1));
|
|
} else {
|
|
jtag_usecs |= (uint32_t)data << (8*(jtag_pos-5));
|
|
}
|
|
}
|
|
if ( ((jtag_tck_delay_value & 0b110) == 0)
|
|
|| (((((jtag_tck_delay_value & 0b110) == 0b100) || (jtag_tck_delay_value & 0b110) == 0b010)) && jtag_pos == 4)
|
|
|| (((jtag_tck_delay_value & 0b110) == 0b110) && jtag_pos == 8)
|
|
)
|
|
{
|
|
tck_delay(jtag_tck_delay_value&1, jtag_num_tck, jtag_usecs);
|
|
jtag_current_command = 0;
|
|
}
|
|
jtag_pos++;
|
|
break;
|
|
|
|
case JTAG_PULSE_TCK_MULTI:
|
|
if (jtag_pos == 0)
|
|
{
|
|
jtag_multi_count = data;
|
|
jtag_multi_pos = 0;
|
|
jtag_multi_multi = 0;
|
|
} else if (jtag_pos == 1)
|
|
{
|
|
jtag_multi_count |= (uint16_t)data << 8;
|
|
} else {
|
|
if (!jtag_multi_multi && !(data & 0x80))
|
|
{
|
|
jtag_multi_multi = data;
|
|
} else {
|
|
if (!jtag_multi_multi) jtag_multi_multi = 1;
|
|
tms = data&1;
|
|
tdi = (data>>1)&1;
|
|
tdo = -1;
|
|
if (data & (1<<2))
|
|
{
|
|
tdo = (data>>3)&1;
|
|
}
|
|
for (i = 0; i < jtag_multi_multi; i++)
|
|
{
|
|
if (!pulse_tck(tms, tdi, tdo)) return 0;
|
|
jtag_multi_pos++;
|
|
}
|
|
jtag_multi_multi = 0;
|
|
}
|
|
if (jtag_multi_pos >= jtag_multi_count)
|
|
jtag_current_command = 0;
|
|
}
|
|
jtag_pos++;
|
|
break;
|
|
|
|
/*
|
|
case JTAG_PULSE_TCK:
|
|
tms = data&1;
|
|
tdi = (data>>1)&1;
|
|
tdo = -1;
|
|
if (data & (1<<2))
|
|
{
|
|
tdo = (data>>3)&1;
|
|
}
|
|
if (!pulse_tck(tms, tdi, tdo)) return 0;
|
|
jtag_current_command = 0;
|
|
break;
|
|
*/
|
|
default:
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void jtag_setup()
|
|
{
|
|
PORT &= ~((1<<TMS_PIN) | (1<<TDO_PIN) | (1<<TDI_PIN)) | (1<<TCK_PIN);
|
|
PORT_DDR |= (1<<TMS_PIN) | (1<<TCK_PIN) | (1<<TDI_PIN);
|
|
PORT_DDR &= ~(1<<TDO_PIN);
|
|
jtag_current_command = 0;
|
|
}
|
|
|
|
void jtag_shutdown()
|
|
{
|
|
PORT &= ~((1<<TMS_PIN) | (1<<TCK_PIN) | (1<<TDO_PIN) | (1<<TDI_PIN));
|
|
PORT_DDR &= ~((1<<TMS_PIN) | (1<<TCK_PIN) | (1<<TDO_PIN) | (1<<TDI_PIN));
|
|
}
|
|
|
|
int jtag_execute(int count, uint8_t* data)
|
|
{
|
|
int i;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
if (!jtag_parse_byte(data[i]))
|
|
{
|
|
jtag_shutdown();
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|