-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathKenwoodXS.ino
145 lines (124 loc) · 3.49 KB
/
KenwoodXS.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
Kenwood XS System Control
See XS-Connection.jpg for pinout.
Based on reverse engineering of the protocol done by Olaf Such ([email protected]).
The following excerpts were taken from de.sci.electronics posts by Olaf from 1997.
"Spezifikationen:
positive Logik, TTL Pegel, Startbit 15ms, 8Bit daten, danach geht
CTRL wieder auf 0V"
"The code consists of: CTRL goes High, 2ms later, SDAT goes High for about
15ms (StartBit), then a Low on SDAT for either approx. 15ms or 7.5ms
followed by a High level on SDAT for 7.5ms (FrameSignal)
then Low again for 15 or 7.5ms, High for 7.5, etc. 8 times all together.
CTRL then returns to Low."
*/
/*
Here are commands for Kenwood KX-3050 cassette deck:
Commands working in both the power-on mode and stand-by mode (in decimal):
121 - play
112, 113, 115, 117, 122, 123, 125 - stop
Commands working only in the power-on mode (in decimal):
66 - search next track
68 - stop
70 - play if stopped or paused, repeat current song if playing
72 - record
74 - search previous track
76 - pause
*/
enum {
SDAT = 2,
CTRL = 3,
BIT_0 = 15000,
BIT_1 = 7500,
PLAY = 121,
STOP1 = 112,
STOP2 = 113,
STOP3 = 115,
STOP4 = 117,
STOP5 = 122,
STOP6 = 123,
STOP7 = 125,
};
void setup() {
Serial.begin(9600);
while (!Serial)
;
// Set-up XS lines
pinMode(CTRL, OUTPUT);
pinMode(SDAT, OUTPUT);
digitalWrite(CTRL, LOW);
digitalWrite(SDAT, LOW);
// Usage
Serial.println("Kenwood KX-3050 commands:");
Serial.println(" Commands working in both the power-on mode and stand-by mode (in decimal):");
Serial.println(" 121 - play");
Serial.println(" 112, 113, 115, 117, 122, 123, 125 - stop");
Serial.println("");
Serial.println(" Commands working only in the power-on mode (in decimal):");
Serial.println(" 66 - search next track");
Serial.println(" 68 - stop");
Serial.println(" 70 - play if stopped or paused, repeat current song if playing");
Serial.println(" 72 - record");
Serial.println(" 74 - search previous track");
Serial.println(" 76 - pause");
Serial.println("");
Serial.println("Now type:");
Serial.println(" value 0-255 to send the corresponding command,");
Serial.println(" value >255 to start a loop to automatically try all commands with delay of 'value' ms.");
}
void send_byte(byte b) {
// StartBit
digitalWrite(SDAT, HIGH);
delay(15);
for (byte mask = 0x80; mask; mask >>= 1) {
// Bit
digitalWrite(SDAT, LOW);
if (b & mask)
delayMicroseconds(BIT_1);
else
delayMicroseconds(BIT_0);
// FrameSignal
digitalWrite(SDAT, HIGH);
delayMicroseconds(7500);
}
}
void send_command(byte cmd) {
Serial.print("Command ");
Serial.print(cmd, DEC);
Serial.print(" / 0x");
Serial.println(cmd, HEX);
digitalWrite(CTRL, HIGH);
delay(2);
send_byte(cmd);
// Return to default state
digitalWrite(CTRL, LOW);
digitalWrite(SDAT, LOW);
}
void try_all(unsigned long wait) {
for (unsigned cmd = 0; cmd < 256; cmd++) {
if(cmd == PLAY ||
cmd == STOP1 ||
cmd == STOP2 ||
cmd == STOP3 ||
cmd == STOP4 ||
cmd == STOP5 ||
cmd == STOP6 ||
cmd == STOP7) {
Serial.println("skipping one uninteresting command");
continue;
}
send_command(byte(cmd));
delay(wait);
}
}
void loop() {
while (Serial.available()) {
const long val = Serial.parseInt();
if (val < 0)
Serial.println("wrong input");
else if (val < 256)
send_command(byte(val));
else
try_all((unsigned long)val);
}
}