Спойлер
// kenwood#define kenwoodPin 14
#define cmdSource 0x13
#define cmdVolumeDown 0x15
#define cmdVolumeUp 0x14
#define cmdUp 0x0B
#define cmdDown 0x0C
#define cmdLeft 0x0A
#define cmdRight 0x0B
#define cmdPlay 0x0E
/////////////////////////////////////////////////////////////////
// джойстик
#define rows 4
#define cols 2
// номера кнопок в соответствии со схемой
const byte keys[rows][cols] =
{
{1,5},
{2,6},
{3,7},
{4,8}
};
// 13 12 10 9 8 7 6 5
// номера пинов
const byte rowPins[rows] = {7, 8, 9, 10}; // строки
const byte colPins[cols] = {12, 13}; // столбцы
// маски для клавиш
#define MaskSRCButton 1
#define MaskPlayButton 2
#define MaskVolumeUpButton 4
#define MaskVolumeDownButton 8
#define MaskLEFTButton 16
#define MaskRIGHTButton 32
#define MaskScrollDown 64
#define MaskScrollUp 128
unsigned long starttime;
bool workkbd;
/////////////////////////////////////////////////////////////////
void setup()
{
int i;
// строки — на выход
for (i = 0; i < rows; ++i)
{
pinMode(rowPins, OUTPUT);
}
// столбцы — на вход
for (i = 0; i < cols; ++i)
{
pinMode(colPins, INPUT_PULLUP); // включаем подтягивающий резистор
}
// управление Alpine
pinMode(kenwoodPin, OUTPUT);
starttime = millis();
workkbd = false;
}
// сканирование джойстика
byte scan(void)
{
int i, j;
byte code = 0;
for (i = 0; i < rows; ++i)
{
digitalWrite(rowPins, LOW);
// кнопки
for (j = 0; j < cols; ++j)
{
if(digitalRead(colPins[j]) == false)
{
code |= 1 << (keys[j] — 1);
}
}
digitalWrite(rowPins, HIGH);
}
return code;
}
// отправка байта
void SendByte(byte data)
{
for (int i = 0; i < 8; ++i)
{
digitalWrite(kenwoodPin, HIGH);
delayMicroseconds(560);
digitalWrite(kenwoodPin, LOW);
if (data & 1)
{ // 1
delayMicroseconds(1680);
}
else
{ // 0
delayMicroseconds(560);
}
data >>= 1;
}
}
// отправка команды
void Send(byte command)
{
digitalWrite(kenwoodPin, HIGH);
delayMicroseconds(9000);
digitalWrite(kenwoodPin, LOW);
delayMicroseconds(4500);
SendByte(0xB9);
SendByte(0x46);
SendByte(command);
SendByte(~command);
digitalWrite(kenwoodPin, HIGH);
delayMicroseconds(560);
digitalWrite(kenwoodPin, LOW);
}
// цикл программы
void loop(void)
{
byte code;
code = scan();
if (workkbd == false)
{
if (millis() — starttime > 3000)
workkbd = true;
return;
}
if (code & MaskSRCButton)
Send(cmdSource);
if (code & MaskPlayButton)
Send(cmdPlay);
if (code & MaskVolumeUpButton)
Send(cmdVolumeUp);
if (code & MaskVolumeDownButton)
Send(cmdVolumeDown);
if (code & MaskLEFTButton)
Send(cmdLeft);
if (code & MaskRIGHTButton)
Send(cmdRight);
if (code & MaskScrollDown)
Send(cmdDown);
if (code & MaskScrollUp)
Send(cmdUp);
}

