Внесу свои 5 копеек в эту тему
Немного поковырял ROM из первого поста, рассмотрел фотографии платы, привожу результаты своих изысканий
Сразу скажу, что ничего из этого на практике не проверялось и такого джойстика у меня нет, так что вполне возможно, я где-то ошибся.
Обмен данными выглядит так: после стандартных 4-х опросов для 6-и кнопочного джойстика 2 младших бита (соответствующие кнопкам вверх и вниз)
порта джойстика переводятся в режим вывода. Бит 6 (сигнал select), вероятно, используется для клок для загрузки данных. Далее в два этапа
загружаются 4 бита данных вибрации (уровень вибрации ?) Игра использует только значения 3,2,0 причем они всегда одинаковые для обоих пар.
Также используется счетчик, который уменьшается на 1 каждый кадр, и когда он достигает 0, значение данных тоже становиться 0. Игра использует
только 2 значения счетчика 255 и 30.
Я написал алгоритм работы с джойстиком данного хака в виде С кода.
# define DELAY_INPUT() asm volatile("nop \n\t nop"); //Usual delay for reading controllers
# define SMALL_DELAY() asm volatile("nop");
typedef unsigned char u8;
typedef unsigned short u16;
struct vibro
{
u8 value; //only bits 0,1,4,5 are used
u8 counter;
};
void reset_vibro_data(struct vibro *p_vibro)
{
p_vibro->value = 0x33;
p_vibro->counter = 0xff;
}
//Called from vblank (after handle_vibro_controller())
void update_vibro_counter(struct vibro *p_vibro)
{
if (p_vibro->counter == 0)
p_vibro->value = 0;
else
p_vibro->counter--;
}
void set_vibro_data(struct vibro *p_vibro, u16 param)
{
if ( param < 0x8000 )
return;
if (param < 0xfffc )
p_vibro->value = 0x33;
else
p_vibro->value = 0x22;
p_vibro->counter = 0x1e;
}
//Called from vblank interrupt handler
void handle_vibro_controller(struct vibro *p_vibro)
{
volatile u8 * data_port = (volatile u8 *)0xA10003;
//1st phase
*data_port = 0x40; //Set select signal
DELAY_INPUT();
u8 btns_lo = *data_port;
*data_port = 0; //Reset select singal
DELAY_INPUT();
u8 btns_hi = *data_port;
//2nd phase
*data_port = 0x40; //Set select signal
DELAY_INPUT();
*data_port = 0; //Reset select signal
DELAY_INPUT();
//3rd phase
*data_port = 0x40; //Set select signal
DELAY_INPUT();
*data_port = 0; //Reset select signal
DELAY_INPUT();
u8 dummy_read = *data_port;
//4th phase
*data_port = 0x40; //Set select signal
DELAY_INPUT();
dummy_read = *data_port;
*data_port = 0x0; //Reset select signal
DELAY_INPUT();
//5th phase
*data_port = 0x40; //Set select signal
volatile u8 * control_port = (volatile u8 *)0xA10009;
*control_port = 0xff; //Set all pins as outputs, enable external interrupt. Should it be 0x43 instead ?
//Write bits 4, 5 to data port
u8 vibro_hi_bits = (p_vibro->value >> 4) & 3;
*data_port = vibro_hi_bits;
vibro_hi_bits |= 0x40; //Latch data ?
SMALL_DELAY();
*data_port = vibro_hi_bits;
DELAY_INPUT();
//Write bits 0, 1 to data port
u8 vibro_lo_bits = p_vibro->value & 3;
*data_port = vibro_lo_bits;
vibro_lo_bits |= 0x40; //Latch data ?
SMALL_DELAY();
*data_port = vibro_lo_bits;
DELAY_INPUT();
*control_port = 0x40; //Return port to standard pad mode (bit 6 is output, others are input, interrupt is disabled)
//process intput...
}
В принципе, можно взять какую-нибудь 5-вольтовую Ардуину, подключить ее к этому джойстику и попробовать послать какую-нибудь команду.
Обвязка капли:
Интересно, как осуществляется управление вибромотором, через ШИМ или линейно через ЦАП ?
И для чего там делитель напряжения (а скорее всего это он, раз там стоят 1% резисторы), это какое-то референсное напряжение, 3.4В ?