[MTCD Android Head Units General] sparky3387:
Works great for me, just so others may also take advantage of this code, I used the below for a Honda Jazz/Fit 2010 with a Kenwood Android Auto Head Unit, I only used the CH+/- and MODE for long press as I did not want to mess with volume triggers and 8 total controls is enough for me (just), not sure if anyone else had an issue but for me the lower resistance (higher potentiometer values) were the only ones that would work with my head unit.

// Car Steering Wheel Rmote w/ Cruise Control Buttons
// lambition
// 10/31/2016

// Using SPI controlled Microchip MCP41100 100K Digital Potentiometer for Output.
// Resistance Value calculated
// Termianl W => Ground, Terminal A => Head Unit Key Input, Terminal B => Leave open
// R_WA: Resistance between Wiper and terminal A.
// R_AB: Resistance between terminal A and B. (100k)
// R_W: Wiper resistance. 125 for 100k chip.
// R_WA(D_n) = ((R_AB * (256-D_n))/256+R_W
// 390.6 ohms per step (100k/256).

// Pin connections
// CS(1) -> 10 (CS)
// SCK(2) -> 13 (SCK)
// SI(3) -> 11 (MOSI)
// Vss (4) -> GND
// PA (5) -> Head Unit Key 1
// PW (6) -> GND
// PB (7) -> Open
// Vdd (8) -> 5V

// First byte is command, Second byte is data. MSB first.

// Command Byte
// X X C1 C0 X X P1 P0
// C1,C0 = 0,1: Write Data, 1,0: Shutdown, Ignore others.
// P1,P0 = 0,1: Select Pot 0, 1,0: Select Pot 1, 1,1: Select Both (P1 is don't care bit for MCP41xxx)

#define CMD_B 0b00010001 // Write Data, Select Pot0. Don't need any other commands.

// Map I/O Pins
#define KEYIN A0 // Key Input
#define CS 10 // Chip select

// Hold time for each button press except pull and push
#define button_hold_ms 500
//Just for programming head unit
//#define button_hold_ms 3000

// Input Key Voltages with 1k pull up resistor
// Change these values to what ever your switch is giving.
#define INPUT_KEYUP_V 315
#define INPUT_KEYDOWN_V 115
#define INPUT_KEYUP_CH 691
#define INPUT_KEYDOWN_CH 501
#define INPUT_KEY_MODE 839

#define TOLERANCE_V 20
#define OFFSET 0.05

// Calculate minimum and maximum ADC values
#define MIN_KEYUP_V_VAL (int)(INPUT_KEYUP_V+OFFSET-TOLERANCE_V)
#define MAX_KEYUP_V_VAL (int)(INPUT_KEYUP_V+OFFSET+TOLERANCE_V)
#define MIN_KEYDOWN_V_VAL (int)(INPUT_KEYDOWN_V+OFFSET-TOLERANCE_V)
#define MAX_KEYDOWN_V_VAL (int)(INPUT_KEYDOWN_V+OFFSET+TOLERANCE_V)
#define MIN_KEYUP_CH_VAL (int)(INPUT_KEYUP_CH+OFFSET-TOLERANCE_V)
#define MAX_KEYUP_CH_VAL (int)(INPUT_KEYUP_CH+OFFSET+TOLERANCE_V)
#define MIN_KEYDOWN_CH_VAL (int)(INPUT_KEYDOWN_CH+OFFSET-TOLERANCE_V)
#define MAX_KEYDOWN_CH_VAL (int)(INPUT_KEYDOWN_CH+OFFSET+TOLERANCE_V)
#define MIN_KEY_MODE_VAL (int)(INPUT_KEY_MODE+OFFSET-TOLERANCE_V)
#define MAX_KEY_MODE_VAL (int)(INPUT_KEY_MODE+OFFSET+TOLERANCE_V)

// Digital Potentiometer Values
#define KEYUP_V_POT 255
#define KEYDOWN_V_POT 254
#define KEYUP_CH_POT 250
#define KEYDOWN_CH_POT 243
#define KEYUPLONG_CH_POT 239
#define KEYDOWNLONG_CH_POT 246
#define KEY_MODE_POT 94
#define KEYLONG_MODE_POT 200

#include <SPI.h>

enum KeyType { OPEN, KEYUP_V, KEYDOWN_V, KEYUP_CH, KEYDOWN_CH, KEYLONGUP_CH, KEYLONGDOWN_CH, KEY_MODE, KEYLONG_MODE };
bool pot_off;
bool debug = false;

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
if (debug) {
while (!Serial) { }
}
debugMessage("BOOT: Serial initialized");
// Configure Pins
pinMode(KEYIN, INPUT);
pinMode(CS, OUTPUT);

digitalWrite(CS, HIGH);

// SPI Initialization
SPI.begin();

DigitalPot_Shutdown(); // Start with Pot off
debugMessage("BOOT: Booted");
}

void loop() {
// put your main code here, to run repeatedly:

static KeyType current_button_state = OPEN;
static KeyType prev_button_state = OPEN;
static KeyType tmp_prev_button_state = OPEN;
static unsigned long button_pressed = 0;
static unsigned long millis_button_held;
static long keyInputValue;
static bool over_sec_processed = true;
static bool prev_long_press = false;

keyInputValue = analogRead(KEYIN); // Read Analog Input
//debugMessage((String)keyInputValue);
KeyType tmp_button_state ;

// Decode Key Inputs
if ( (keyInputValue <= MAX_KEYUP_V_VAL) && (keyInputValue >= MIN_KEYUP_V_VAL)) // Key Up Detected
{
tmp_button_state = KEYUP_V;
}
else if ( (keyInputValue <= MAX_KEYDOWN_V_VAL) && (keyInputValue >= MIN_KEYDOWN_V_VAL)) // Key Down Detected
{
tmp_button_state = KEYDOWN_V;
}
else if ( (keyInputValue <= MAX_KEYUP_CH_VAL) && (keyInputValue >= MIN_KEYUP_CH_VAL)) // Key Pull Detected
{
tmp_button_state = KEYUP_CH;
}
else if ( (keyInputValue <= MAX_KEYDOWN_CH_VAL) && (keyInputValue >= MIN_KEYDOWN_CH_VAL)) // Key Push Detected
{
tmp_button_state = KEYDOWN_CH;
}
else if ( (keyInputValue <= MAX_KEY_MODE_VAL) && (keyInputValue >= MIN_KEY_MODE_VAL)) // Key Push Detected
{
tmp_button_state = KEY_MODE;
}
else
{
tmp_button_state = OPEN; // Mark key not pressed and Ignore out of spec values.
}

// Input State Changes
if (tmp_button_state != tmp_prev_button_state)
{
button_pressed = millis();
over_sec_processed = false;
}

if ((millis() - button_pressed) > 10) // 10 ms debounce delay
{
current_button_state = tmp_button_state;
}

tmp_prev_button_state = tmp_button_state;

if ( (current_button_state != OPEN) && (current_button_state == prev_button_state) ) // Button Held
{
millis_button_held = millis() - button_pressed;
}
//Button is now in open
if ( (current_button_state == OPEN)) // Key released
{
//debugMessage("STATE: OPEN");
if ((millis_button_held < 1000) && (!prev_long_press)) // Key was pressed less than 1 second and previous button was not a long press.
{
if (prev_button_state == KEYUP_CH) // If last button pressed was Keyup send keyup
{
debugMessage("ACTION: SHORT KEYUP_CH");
DigitalPot_Write(KEYUP_CH_POT);
delay(button_hold_ms);
DigitalPot_Shutdown();
}
else if (prev_button_state == KEYDOWN_CH) // If last button pressed was Keydown send keydown.
{
debugMessage("ACTION: SHORT KEYDOWN_CH");
DigitalPot_Write(KEYDOWN_CH_POT);
delay(button_hold_ms);
DigitalPot_Shutdown();
}
else if (prev_button_state == KEY_MODE) // If last button pressed was Keydown send keydown.
{
debugMessage("ACTION: SHORT KEYMODE");
DigitalPot_Write(KEY_MODE_POT);
delay(button_hold_ms);
DigitalPot_Shutdown();
}

else if (!pot_off) // For all other keys, shutoff pot upon releasing button, unless already off.
{
DigitalPot_Shutdown();
}
}
prev_long_press = false;
}
else if ( (current_button_state == KEYUP_CH) || (current_button_state == KEYDOWN_CH) || (current_button_state == KEY_MODE) ) // Key up or down
{

if ( (millis_button_held >= 1000) && (!over_sec_processed) ) // Over 1 second
{

if (prev_button_state == KEYUP_CH)
{
debugMessage("ACTION: LONG KEYUP_CH");
DigitalPot_Write(KEYUPLONG_CH_POT);
delay(button_hold_ms);
DigitalPot_Shutdown();
}
else if (prev_button_state == KEYDOWN_CH)
{
debugMessage("ACTION: LONG KEYDOWN_CH");
DigitalPot_Write(KEYDOWNLONG_CH_POT);
delay(button_hold_ms);
DigitalPot_Shutdown();
}
else if (prev_button_state == KEY_MODE)
{
debugMessage("ACTION: LONG KEYMODE");
DigitalPot_Write(KEYLONG_MODE_POT);
delay(button_hold_ms);
DigitalPot_Shutdown();
}
over_sec_processed = true;
prev_long_press = true;
}

if (millis_button_held >= 2000) // Over 2 seconds
{
delay(1000); // Wait 1 sec between signal
over_sec_processed = false; // Send

}
}
else if ( current_button_state == KEYUP_V )
{
if (pot_off) // Write to Pot only once
{
debugMessage("ACTION: SHORT KEYUP_V");
DigitalPot_Write(KEYUP_V_POT);
}
prev_long_press = false;
}
else if ( current_button_state == KEYDOWN_V )
{
if (pot_off) // Write to Pot only once
{
debugMessage("ACTION: SHORT KEYDOWN_V");
DigitalPot_Write(KEYDOWN_V_POT);
}
prev_long_press = false;
}

prev_button_state = current_button_state;
}

void DigitalPot_Write(const byte data)
{
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); //10MHz, MSB First, Ouput on rising edge.
digitalWrite(CS, LOW);
SPI.transfer(CMD_B); // Send Command
SPI.transfer(data); // send Data
digitalWrite(CS, HIGH);
SPI.endTransaction();
pot_off = false;
}

void DigitalPot_Shutdown()
{
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); //10MHz, MSB First, Ouput on rising edge.
digitalWrite(CS, LOW);
SPI.transfer(0b00100001); //Shutdown Command
SPI.transfer(0); // Dummy data
digitalWrite(CS, HIGH);
SPI.endTransaction();
pot_off = true;
}
void debugMessage(String message) {
if (debug) {
Serial.println(message);
}
}