Загрузить исходник psx.c
#include "psx.h"
#include <util/delay.h>
// буфер
static uint8_t _psx_data[21];
// отправить байт программным SPI и получить ответ
uint8_t _psx_gamepad_shift(uint8_t transmit_byte) {
uint8_t received_byte = 0;
for(uint8_t i = 0; i < 8; i++) {
PSX_SCK_PORT &= ~_BV(PSX_SCK_PIN);
if (transmit_byte & (_BV(i))) {
PSX_DC_PORT |= _BV(PSX_DC_PIN);
}
else {
PSX_DC_PORT &= ~_BV(PSX_DC_PIN);
}
_delay_us(CTRL_CLK);
PSX_SCK_PORT |= _BV(PSX_SCK_PIN);
if(PSX_DATA_PINREG & _BV(PSX_DATA_PIN)) {
received_byte |= _BV(i);
}
_delay_us(CTRL_CLK);
}
PSX_SCK_PORT |= _BV(PSX_SCK_PIN);
return received_byte;
}
// отправить команду
void _psx_send_command(uint8_t send_data[], uint8_t size){
PSX_CS_PORT &= ~(_BV(PSX_CS_PIN));
PSX_DC_PORT |= _BV(PSX_DC_PIN);
PSX_SCK_PORT |= _BV(PSX_SCK_PIN);
for (uint8_t i = 0; i < size; i++){
send_data[i] = _psx_gamepad_shift(send_data[i]);
}
PSX_CS_PORT |= _BV(PSX_CS_PIN);
}
// обновить состояние кнопок
void psx_read_gamepad() {
_psx_data[0] = 0x01;
_psx_data[1] = 0x42;
for (uint8_t i = 2; i < 21; i++){
_psx_data[i] = 0x00;
}
_psx_send_command(_psx_data, 21);
}
// инициализация геймпада
void psx_init(bool analog){
PSX_SCK_DDR |= _BV(PSX_SCK_PIN);
PSX_CS_DDR |= _BV(PSX_CS_PIN);
PSX_DC_DDR |= _BV(PSX_DC_PIN);
PSX_DATA_DDR &= ~(_BV(PSX_DATA_PIN));
PSX_DATA_PORT |= _BV(PSX_DATA_PIN);
PSX_SCK_PORT |= _BV(PSX_SCK_PIN);
PSX_DC_PORT |= _BV(PSX_DC_PIN);
psx_read_gamepad();
if(!analog) return;
// войти в режим конфигурации
uint8_t enter_config_command[] = {0x01, 0x43, 0x00, 0x01, 0x00};
_psx_send_command(enter_config_command, 5);
// заблокирвать геймпад в аналоговом режиме
uint8_t lock_analog_mode_command[] = {0x01, 0x44, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00};
_psx_send_command(lock_analog_mode_command, 9);
// выйти из режима конфигурации
uint8_t exit_config_command[] = {0x01, 0x43, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A};
_psx_send_command(exit_config_command, 9);
}
// получить состояние всех кнопок
uint16_t psx_buttons() {
uint16_t buttons = *(uint16_t*)(_psx_data + 3); // получить 2 байта, содержащих позиции данных 3 и 4
return ~buttons;
}
// получить состояниие кнопки (PSB_x
uint8_t psx_button(uint16_t button) {
uint16_t buttons = psx_buttons();
return ((buttons & button) > 0);
}
// получить состояниие оси джойстика (PSS_x)
uint8_t psx_stick(unsigned int stick) {
return _psx_data[stick];
}