Skip to content

Instantly share code, notes, and snippets.

@halferty
Last active January 17, 2017 08:55
Show Gist options
  • Save halferty/d234a3ca9dffd151c572ddc919e414b8 to your computer and use it in GitHub Desktop.
Save halferty/d234a3ca9dffd151c572ddc919e414b8 to your computer and use it in GitHub Desktop.
Arduino Apple ADB fun
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c\n"
#define BYTE_TO_BINARY(val) \
(val & 0x80 ? '1' : '0'), \
(val & 0x40 ? '1' : '0'), \
(val & 0x20 ? '1' : '0'), \
(val & 0x10 ? '1' : '0'), \
(val & 0x8 ? '1' : '0'), \
(val & 0x4 ? '1' : '0'), \
(val & 0x2 ? '1' : '0'), \
(val & 0x1 ? '1' : '0')
void setup() {
Serial.begin(9600);
pinMode(2, INPUT_PULLUP);
}
#define NUM 256
unsigned long startTime, endTime, diff;
unsigned long diffs[NUM];
unsigned long index = 0;
unsigned char command;
char printBuffer[64];
boolean waitingForStart = true;
unsigned char deviceId = 3;
void writeOne() {
digitalWrite(2, LOW);
delayMicroseconds(35);
digitalWrite(2, HIGH);
delayMicroseconds(65);
}
void writeZero() {
digitalWrite(2, LOW);
delayMicroseconds(65);
digitalWrite(2, HIGH);
delayMicroseconds(35);
}
unsigned long readPulse() {
while(digitalRead(2)) {}
startTime = micros();
while(!digitalRead(2)) {}
endTime = micros();
return (endTime - startTime);
}
boolean isHigh(unsigned long d) {
return (d > (35 - 10) && d < (35 + 10));
}
boolean isLow(unsigned long d) {
return (d > (65 - 10) && d < (65 + 10));
}
void loop() {
diff = readPulse();
if (diff > 750 && diff < 850) {
index = 0;
waitingForStart = false;
} else if (!waitingForStart) {
diffs[index] = diff;
index++;
if (index == 8) {
command = 0;
for (index = 0; index < 8; index++) {
if (isHigh(diffs[index])) {
command |= (1 << (7 - index));
} else if (isLow(diffs[index])) {
command &= ~(1 << (7 - index));
}
}
if (command >> 4 == deviceId) {
if (((command >> 2) & 3) == 3) {
// Talk command
if (command & 3 == 3) {
// Register 3
// Respond with some stuff
delayMicroseconds(200);
pinMode(2, OUTPUT);
// '1' Start bit
writeOne();
// 15 reserved, 0
writeZero();
// 14 exceptional event, device specific, 1 if unused
writeOne();
// 13 service request enable, 1 = enabled
writeOne();
// 12 reserved, 0
writeZero();
// 11
// 10
// 9
// 8 address
// Send a random address, which is just going to be hardcoded as 6 here, because I'm lazy
writeZero();
writeOne();
writeOne();
writeZero();
// 7
// 6
// 5
// 4
// 3
// 2
// 1
// 0 device handler id
writeZero();
writeZero();
writeZero();
writeZero();
writeZero();
writeZero();
writeZero();
writeOne();
// '0' stop bit
writeZero();
pinMode(2, INPUT_PULLUP);
} else if (command & 3 == 0) {
// Register 0
// Respond with some stuff
delayMicroseconds(200);
pinMode(2, OUTPUT);
// '1' Start bit
writeOne();
// 15 button status, 0 = down
writeOne();
// 14
// 13
// 12
// 11
// 10
// 9
// 8 Y move counts 2's complement form, negative = up
writeZero();
writeZero();
writeZero();
writeZero();
writeZero();
writeZero();
writeZero();
// 7 not used (always 0)
writeZero();
// 6
// 5
// 4
// 3
// 2
// 1
// 0 X move counts, negative = left
writeZero();
writeZero();
writeZero();
writeZero();
writeZero();
writeZero();
writeOne();
// '0' stop bit
writeZero();
pinMode(2, INPUT_PULLUP);
}
} else if (((command >> 2) & 3) == 2) {
// Listen command
// Listen Register 3
if (command & 3 == 3) {
for(index = 0; index < 19; index++) {
diffs[index] = readPulse();
}
deviceId = (isHigh(diffs[6]) << 3) | (isHigh(diffs[7]) << 2) | (isHigh(diffs[8]) << 1) | (isHigh(diffs[9]));
sprintf(printBuffer, "Going to DeviceId: %d\n", deviceId);
Serial.print(printBuffer);
for(index = 0; index < 19; index++) {
sprintf(printBuffer, "%d\n", (isLow(diffs[index])) ? 0 : (isHigh(diffs[index])) ? 1 : diffs[index]);
Serial.print(printBuffer);
}
Serial.print("Done.\n");
// TODO: The host keeps sending us to different IDs (27 times!) and then polls register 0 very infrequently, so this is probably working wrongly? Or do we just need to do a sysrequest to actually send data?
// (That's done by effectively wiping out the stop bit on any host command, holding it low for a total of 300usec. Then it waits to be addressed. If the host addresses some other device instead, do it again).
} else {
sprintf(printBuffer, BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(command));
Serial.print(printBuffer);
Serial.print("Unknown Listen command:\n");
for(index = 0; index < NUM; index++) {
diffs[index] = readPulse();
}
for(index = 0; index < NUM; index++) {
sprintf(printBuffer, "%d\n", (isLow(diffs[index])) ? 0 : (isHigh(diffs[index])) ? 1 : diffs[index]);
Serial.print(printBuffer);
}
Serial.print("Done.\n");
while(1) {}
}
}
sprintf(printBuffer, BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(command));
Serial.print(printBuffer);
}
index = 0;
waitingForStart = true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment