├── README.md └── Arduino:328P Sketches ├── CCDArduino328pReadUARTStream └── CCDArduino328pReadUARTStream.ino ├── In Progress:Trial ├── CCDArduino328pSendUARTPrimative │ └── CCDArduino328pSendFromSerialSCI.ino ├── CCDArduino328pSendUARTSingle │ └── CCDArduino328pSendFromSerialSCIV3ExtOscNoMonitor.ino └── UARTSENDTEST2 │ └── UARTSENDTEST2.ino ├── CCDArduino328pReadUARTSingle └── CCDArduino328pReadUARTSingle.ino ├── CCDArduino328pSendUARTSingle └── CCDArduino328pSendUARTSingle.ino └── CCDArduino328pUARTAlpineControlExtOsc └── CCDArduino328pUARTAlpineControlExtOsc.ino /README.md: -------------------------------------------------------------------------------- 1 | # chrysler-ccd 2 | 3 | Collection of Arduino sketches for interacting with the data bus utilized on various Chrysler vehicles circa 1980-2000. 4 | 5 | Basic code to read the Chrysler CCD bus via UART. Write code is being worked on by Chris O and Chris (Ascension) at the moment 3-26-2016. 6 | 7 | 1MHz clock generation done via external oscillator (PN MXO45HS-3C-1M0000 - available @ DigiKey). 8 | 9 | Sketch utilizes Intersil CDP68HC68S1E. Is available through eBay and AliExpress 10 | 11 | IC wiring, OBD2 wiring, captured/decode data, and misc data is available at: 12 | 13 | https://docs.google.com/spreadsheets/d/1-7Ahhgu7fPNAfORWXrjADwHnI8PiozMbrc1AF3RrglQ/edit?usp=sharing 14 | -------------------------------------------------------------------------------- /Arduino:328P Sketches/CCDArduino328pReadUARTStream/CCDArduino328pReadUARTStream.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SCI Code - Read to Serial 3 | */ 4 | 5 | #include 6 | 7 | 8 | int idlePin = 2; //Idle pin /INT0 9 | int controlPin = 3; 10 | int ledPin = 13; 11 | 12 | 13 | AltSoftSerial mySerial; // RX, TX 14 | 15 | void setup() { 16 | 17 | pinMode(idlePin, INPUT); //set idle pin for input 18 | pinMode(controlPin, INPUT); //set control pin for input 19 | pinMode(ledPin, OUTPUT); //prep builtin led pin 20 | 21 | 22 | Serial.begin(57600); //have had issues at 115200, so 57600 seems to work fine. 23 | mySerial.begin(7812.5); //for serial IC 24 | 25 | 26 | attachInterrupt(digitalPinToInterrupt(idlePin), endofstring, CHANGE); 27 | 28 | } 29 | 30 | 31 | void loop() { 32 | if (mySerial.available()) { //Waits for available data 33 | 34 | Serial.print(mySerial.read()); //Prints the data as it comes in 35 | Serial.print(" "); //Prints a space as a delimiter 36 | 37 | } 38 | /*if (mySerial.read()) == "130,32,32,0,194,"{ 39 | digitalWrite(ledPin, HIGH); 40 | 41 | else 42 | 43 | digitalWrite(ledPin, LOW); 44 | } 45 | */ 46 | } 47 | 48 | 49 | void endofstring() { 50 | Serial.print("\n"); 51 | } //When IDLE changes, print a new line. Two new lines per message string. One high to low, another low to high. Have had issues with only going to low and strings running together. Likely a timing/speed issue. 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Arduino:328P Sketches/In Progress:Trial/CCDArduino328pSendUARTPrimative/CCDArduino328pSendFromSerialSCI.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SCI Code - Send Command 3 | 4 | By Chris Souers 5 | 6 | Sends commands without regard to if the data was seen on the bus or not. Does not check for reflected bytes as it should. Needs improved upon, but works okay for now. Should not be a problem when bus is idle/asleep. 7 | 8 | */ 9 | 10 | 11 | #include 12 | 13 | 14 | int idlePin = 2; //Idle pin /INT0 15 | int controlPin = 3; 16 | int ledPin = 13; 17 | 18 | int idleStatus = 0; 19 | int ledStatus = 0; 20 | int readytosend = 0; 21 | 22 | byte byte1 = 0; //Data to send 23 | byte byte2 = 0; 24 | byte byte3 = 0; 25 | byte byte4 = 0; 26 | byte byte5 = 0; 27 | byte byte6 = 0; 28 | 29 | 30 | AltSoftSerial mySerial; // RX, TX 31 | 32 | void setup() { 33 | 34 | pinMode(idlePin, INPUT); //set idle pin for input 35 | pinMode(controlPin, INPUT); //set control pin for input 36 | pinMode(ledPin, OUTPUT); //prep builtin led pin 37 | 38 | 39 | Serial.begin(57600); //have had issues at 115200, so 57600 seems to work fine. 40 | mySerial.begin(7812.5); //for serial IC 41 | 42 | 43 | //attachInterrupt(digitalPinToInterrupt(triggerPin), send, CHANGE); 44 | 45 | 46 | } 47 | 48 | void loop() { 49 | if (Serial.available() > 0) { 50 | byte1 = Serial.parseInt(); 51 | byte2 = Serial.parseInt(); 52 | byte3 = Serial.parseInt(); 53 | byte4 = Serial.parseInt(); 54 | //byte5 = Serial.parseInt(); 55 | //byte6 = Serial.parseInt(); 56 | readytosend = Serial.parseInt(); 57 | 58 | //To send data, open serial monitor. Input data string, in decimal, with spaces in between each followed by 1. 59 | //Example: "206 116 151 238 190 133 1" 60 | } 61 | 62 | //delay(100); 63 | idleStatus = digitalRead(idlePin); 64 | if (idleStatus == 0 && readytosend == 1) { 65 | mySerial.write(byte1); //sends the first byte 66 | mySerial.write(byte2); 67 | mySerial.write(byte3); 68 | mySerial.write(byte4); 69 | //mySerial.write(byte5); 70 | // mySerial.write(byte6); 71 | readytosend = 0; //1 will continually send data. Change to 0 for sending only once per serial input 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Arduino:328P Sketches/CCDArduino328pReadUARTSingle/CCDArduino328pReadUARTSingle.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Code adapted from Chris O. and Juha Niinikoski 3 | 4 | Prints ID Byte, sent via serial monitor from PC, to serial monitor. 5 | */ 6 | 7 | 8 | 9 | 10 | #include 11 | #include 12 | 13 | int idlePin = 2; //Idle pin /INT0 on Atmega328P 14 | int controlPin = 3; //Control pin /INT1 on Atmega328P. Not being used as an interrupt right now 15 | int ledPin = 13; //Onboard LED pin incase we need it 16 | 17 | byte ccd_buff[8]; /* CCD receive buffer / MAX 8 Bytes */ 18 | int ccd_buff_ptr; /* CCD receive buffer pointer */ 19 | volatile byte IdleOnOffFlag = 0; //variable for the idle pin. Must be volatile due to being part of interrupt 20 | boolean DataComplete = false; //variable for declaring end of message string. Can be True or False. 21 | 22 | AltSoftSerial mySerial(6, 7); // RX, TX 23 | 24 | volatile byte selectbyte = 134; //ID byte to print to the serial monitor 25 | 26 | void setup() { 27 | 28 | 29 | pinMode(idlePin, INPUT); //set idle pin for input 30 | //pinMode(controlPin, INPUT); //set control pin for input 31 | pinMode(ledPin, OUTPUT); //prep builtin led pin 32 | pinMode(4, OUTPUT); //Alpine control pin 33 | 34 | digitalWrite(ledPin, LOW); //Set LED to low once. May be unnecessary but doesn't hurt anything. 35 | //watchdogSetup(); 36 | // setup 1MHz generator for CDP68HC68S1 IC 37 | Serial.begin(57600); 38 | mySerial.begin(7812.5); //for serial IC 39 | 40 | attachInterrupt(digitalPinToInterrupt(idlePin), endofstring, RISING); 41 | } 42 | void watchdogSetup() { 43 | cli(); // disable all interrupts 44 | wdt_reset(); // reset the WDT timer 45 | WDTCSR |= (1 << WDCE) | (1 << WDE); 46 | WDTCSR = (0 << WDIE) | (1 << WDE) | (0 << WDP3) | (1 << WDP2) | (1 << WDP1) | (0 << WDP0); //1000ms WDT timer 47 | sei(); 48 | } 49 | 50 | void endofstring() { 51 | IdleOnOffFlag = 1; //Sets flag high when idle pin goes high 52 | } 53 | 54 | void loop() { 55 | wdt_reset(); 56 | if (Serial.available() > 0) { 57 | selectbyte = Serial.parseInt(); 58 | } 59 | 60 | while (mySerial.available()) { 61 | 62 | byte data = mySerial.read(); 63 | ccd_buff[ccd_buff_ptr] = data; // read & store character 64 | ccd_buff_ptr++; // increment the pointer to the next byte 65 | } 66 | if (IdleOnOffFlag == 1) { // check the CDP68HC68S1 IDLE pin interrupt flag, change from Low to High. 67 | process_data(); // GOTO process_data loop 68 | IdleOnOffFlag = 0; //RESET IDLE PIN FLAG 69 | ccd_buff_ptr = 0; // RESET buffer pointer to byte 0 for data to be overwritten 70 | } 71 | } 72 | 73 | void process_data() { 74 | if (ccd_buff[0] == selectbyte) { 75 | 76 | Serial.print((int)ccd_buff[0]); 77 | Serial.print(" "); 78 | Serial.print((int)ccd_buff[1]); 79 | Serial.print(" "); 80 | Serial.print((int)ccd_buff[2]); 81 | Serial.print(" "); 82 | Serial.print((int)ccd_buff[3]); 83 | Serial.print(" "); 84 | Serial.print((int)ccd_buff[4]); 85 | Serial.print(" "); 86 | Serial.println((int)ccd_buff[5]); 87 | 88 | ccd_buff[0] = 0; 89 | ccd_buff[1] = 0; 90 | ccd_buff[2] = 0; 91 | ccd_buff[3] = 0; 92 | ccd_buff[4] = 0; 93 | ccd_buff[5] = 0; 94 | } 95 | 96 | else{ 97 | ccd_buff[0] = 0; 98 | ccd_buff[1] = 0; 99 | ccd_buff[2] = 0; 100 | ccd_buff[3] = 0; 101 | ccd_buff[4] = 0; 102 | ccd_buff[5] = 0; 103 | } 104 | } 105 | 106 | 107 | -------------------------------------------------------------------------------- /Arduino:328P Sketches/CCDArduino328pSendUARTSingle/CCDArduino328pSendUARTSingle.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SCI Code - Send Command 3 | 4 | By Chris Souers 5 | 6 | Sends commands 7 | */ 8 | 9 | 10 | volatile int readytosend = 0; //set to 1 to send data 11 | volatile byte send_buff[5]; /* CCD send buffer / MAX 4-5 Bytes */ 12 | volatile int send_buff_ptr; /* CCD send buffer pointer */ 13 | 14 | #define idlePin 2 //INT0 on 328P 15 | #define controlPin 3 //INT1 on 328P 16 | #define ledPin 13 17 | 18 | #include 19 | 20 | volatile byte ccd_buff[5]; /* CCD receive buffer / MAX 8 Bytes */ 21 | volatile int ccd_buff_ptr; /* CCD receive buffer pointer */ 22 | volatile int IdleOnOffFlag = 1; //variable for the idle pin. Must be volatile due to being part of interrupt 23 | 24 | AltSoftSerial mySerial; // RX, TX //SoftwareSerial may work better for SBIC - pins (6,7); 25 | 26 | 27 | void setup() { 28 | 29 | pinMode(idlePin, INPUT); //set idle pin for input 30 | pinMode(ledPin, OUTPUT); //prep builtin led pin 31 | digitalWrite(ledPin, LOW); //Turn D13 LED Off 32 | 33 | mySerial.begin(7812.5); //for serial IC 34 | Serial.begin(57600); //for serial monitor 35 | Serial.println("Serial Prompt Ready - GO"); 36 | delay(1000); 37 | 38 | //attachInterrupt(digitalPinToInterrupt(idlePin), endofstring, CHANGE); 39 | } 40 | 41 | 42 | void endofstring() { 43 | 44 | IdleOnOffFlag = digitalRead(idlePin); 45 | //digitalWrite(ledPin, IdleOnOffFlag); 46 | 47 | } 48 | 49 | 50 | void loop() { 51 | 52 | if (Serial.available() > 0) { //reads 4 data bytes in, plus 1 for the ready switches 53 | for (send_buff_ptr = 0; send_buff_ptr <= 2; send_buff_ptr++) { 54 | send_buff[send_buff_ptr] = Serial.parseInt(); 55 | } 56 | readytosend = Serial.parseInt(); 57 | ccd_buff_ptr = 0; 58 | send_buff_ptr = 0; 59 | } 60 | endofstring(); //continually checks for idle flag state 61 | 62 | if (IdleOnOffFlag == 0 && readytosend == 1) { 63 | 64 | send_data(); 65 | 66 | } 67 | 68 | } 69 | 70 | void send_data() { 71 | 72 | while (mySerial.available()) { 73 | if (send_buff_ptr == 0) { 74 | delayMicroseconds(256); //uart loading delay maybe not necessary. Can be checked with scope. 75 | } 76 | 77 | mySerial.write(send_buff[send_buff_ptr]); 78 | 79 | ccd_buff[ccd_buff_ptr] = mySerial.read(); 80 | 81 | if (send_buff_ptr == 0 && send_buff[send_buff_ptr] != ccd_buff[ccd_buff_ptr]) { 82 | data_reset(); 83 | break; 84 | } 85 | 86 | if (send_buff_ptr >= 1 && send_buff[send_buff_ptr] != ccd_buff[ccd_buff_ptr]) { 87 | delayMicroseconds(1280); //EOM software delay 88 | data_reset(); 89 | break; 90 | } 91 | 92 | if (send_buff[send_buff_ptr] == ccd_buff[ccd_buff_ptr]) { 93 | ccd_buff_ptr++; 94 | send_buff_ptr++; 95 | } 96 | 97 | if (send_buff_ptr >= 4) { 98 | readytosend = 0; 99 | delayMicroseconds(1280); //EOM software delay 100 | data_reset(); 101 | break; 102 | } 103 | 104 | } 105 | } 106 | 107 | void data_reset() { 108 | Serial.println("Reset"); 109 | 110 | /* 111 | if (ccd_buff_ptr >= 1) { 112 | readytosend = 0; 113 | for (ccd_buff_ptr = 0; ccd_buff_ptr <= 4; ccd_buff_ptr++) { 114 | ccd_buff[ccd_buff_ptr] = 0; 115 | } 116 | 117 | for (send_buff_ptr = 0; send_buff_ptr <= 4; send_buff_ptr++) { 118 | send_buff[send_buff_ptr] = 0; 119 | } 120 | } 121 | */ 122 | //delay(25); 123 | ccd_buff_ptr = 0; 124 | send_buff_ptr = 0; 125 | 126 | 127 | } 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /Arduino:328P Sketches/In Progress:Trial/CCDArduino328pSendUARTSingle/CCDArduino328pSendFromSerialSCIV3ExtOscNoMonitor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SCI Code - Send Command 3 | 4 | By Chris Souers 5 | 6 | Sends commands 7 | */ 8 | 9 | 10 | volatile int readytosend = 0; //set to 1 to send data 11 | volatile byte send_buff[5]; /* CCD send buffer / MAX 4-5 Bytes */ 12 | volatile int send_buff_ptr; /* CCD send buffer pointer */ 13 | 14 | #define idlePin 2 //INT0 on 328P 15 | #define controlPin 3 //INT1 on 328P 16 | #define ledPin 13 17 | 18 | #include 19 | 20 | volatile byte ccd_buff[5]; /* CCD receive buffer / MAX 8 Bytes */ 21 | volatile int ccd_buff_ptr; /* CCD receive buffer pointer */ 22 | volatile int IdleOnOffFlag = 1; //variable for the idle pin. Must be volatile due to being part of interrupt 23 | 24 | AltSoftSerial mySerial; // RX, TX //SoftwareSerial may work better for SBIC - pins (6,7); 25 | 26 | 27 | void setup() { 28 | 29 | pinMode(idlePin, INPUT); //set idle pin for input 30 | pinMode(ledPin, OUTPUT); //prep builtin led pin 31 | digitalWrite(ledPin, LOW); //Turn D13 LED Off 32 | 33 | mySerial.begin(7812.5); //for serial IC 34 | Serial.begin(57600); //for serial monitor 35 | Serial.println("Serial Prompt Ready - GO"); 36 | delay(1000); 37 | 38 | //attachInterrupt(digitalPinToInterrupt(idlePin), endofstring, CHANGE); 39 | } 40 | 41 | 42 | void endofstring() { 43 | 44 | IdleOnOffFlag = digitalRead(idlePin); 45 | //digitalWrite(ledPin, IdleOnOffFlag); 46 | 47 | } 48 | 49 | 50 | void loop() { 51 | 52 | if (Serial.available() > 0) { //reads 4 data bytes in, plus 1 for the ready switches 53 | for (send_buff_ptr = 0; send_buff_ptr <= 2; send_buff_ptr++) { 54 | send_buff[send_buff_ptr] = Serial.parseInt(); 55 | } 56 | readytosend = Serial.parseInt(); 57 | ccd_buff_ptr = 0; 58 | send_buff_ptr = 0; 59 | } 60 | endofstring(); //continually checks for idle flag state 61 | 62 | if (IdleOnOffFlag == 0 && readytosend == 1) { 63 | 64 | send_data(); 65 | 66 | } 67 | 68 | } 69 | 70 | void send_data() { 71 | 72 | while (mySerial.available()) { 73 | if (send_buff_ptr == 0) { 74 | delayMicroseconds(256); //uart loading delay maybe not necessary. Can be checked with scope. 75 | } 76 | 77 | mySerial.write(send_buff[send_buff_ptr]); 78 | 79 | ccd_buff[ccd_buff_ptr] = mySerial.read(); 80 | 81 | if (send_buff_ptr == 0 && send_buff[send_buff_ptr] != ccd_buff[ccd_buff_ptr]) { 82 | data_reset(); 83 | break; 84 | } 85 | 86 | if (send_buff_ptr >= 1 && send_buff[send_buff_ptr] != ccd_buff[ccd_buff_ptr]) { 87 | delayMicroseconds(1280); //EOM software delay 88 | data_reset(); 89 | break; 90 | } 91 | 92 | if (send_buff[send_buff_ptr] == ccd_buff[ccd_buff_ptr]) { 93 | ccd_buff_ptr++; 94 | send_buff_ptr++; 95 | } 96 | 97 | if (send_buff_ptr >= 4) { 98 | readytosend = 0; 99 | delayMicroseconds(1280); //EOM software delay 100 | data_reset(); 101 | break; 102 | } 103 | 104 | } 105 | } 106 | 107 | void data_reset() { 108 | Serial.println("Reset"); 109 | 110 | /* 111 | if (ccd_buff_ptr >= 1) { 112 | readytosend = 0; 113 | for (ccd_buff_ptr = 0; ccd_buff_ptr <= 4; ccd_buff_ptr++) { 114 | ccd_buff[ccd_buff_ptr] = 0; 115 | } 116 | 117 | for (send_buff_ptr = 0; send_buff_ptr <= 4; send_buff_ptr++) { 118 | send_buff[send_buff_ptr] = 0; 119 | } 120 | } 121 | */ 122 | //delay(25); 123 | ccd_buff_ptr = 0; 124 | send_buff_ptr = 0; 125 | 126 | 127 | } 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /Arduino:328P Sketches/In Progress:Trial/UARTSENDTEST2/UARTSENDTEST2.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SCI Code - Send Command 3 | 4 | By Chris Souers 5 | 6 | Sends commands 7 | */ 8 | 9 | 10 | volatile int readytosend = 0; //set to 1 to send data 11 | volatile byte send_buff[4]; /* CCD send buffer / MAX 4-5 Bytes */ 12 | volatile int send_buff_ptr; /* CCD send buffer pointer */ 13 | 14 | #define idlePin 2 //INT0 on 328P 15 | #define controlPin 3 //INT1 on 328P 16 | #define ledPin 13 17 | 18 | #include 19 | //#include 20 | 21 | volatile byte ccd_buff[4]; /* CCD receive buffer / MAX 8 Bytes */ 22 | volatile int ccd_buff_ptr; /* CCD receive buffer pointer */ 23 | volatile int IdleOnOffFlag = 1; //variable for the idle pin. Must be volatile due to being part of interrupt 24 | 25 | AltSoftSerial mySerial; // RX, TX //SoftwareSerial may work better for SBIC - pins (6,7); 26 | //SoftwareSerial mySerial (8, 9); // RX, TX //SoftwareSerial may work better for SBIC - pins (6,7); 27 | 28 | 29 | void setup() { 30 | 31 | pinMode(idlePin, INPUT); //set idle pin for input 32 | pinMode(ledPin, OUTPUT); //prep builtin led pin 33 | digitalWrite(ledPin, LOW); //Turn D13 LED Off 34 | 35 | mySerial.begin(7812.5); //for serial IC 36 | Serial.begin(115200); //for serial monitor 37 | Serial.println("Serial Prompt Ready - GO"); 38 | 39 | //attachInterrupt(digitalPinToInterrupt(idlePin), endofstring, CHANGE); 40 | } 41 | 42 | 43 | void endofstring() { 44 | 45 | IdleOnOffFlag = digitalRead(idlePin); 46 | //digitalWrite(ledPin, IdleOnOffFlag); 47 | 48 | } 49 | 50 | 51 | void loop() { 52 | 53 | if (Serial.available() > 0) { //reads 4 data bytes in, plus 1 for the ready switches 54 | for (send_buff_ptr = 0; send_buff_ptr <= 3; send_buff_ptr++) { 55 | send_buff[send_buff_ptr] = Serial.parseInt(); 56 | } 57 | readytosend = Serial.parseInt(); 58 | ccd_buff_ptr = 0; 59 | send_buff_ptr = 0; 60 | } 61 | 62 | endofstring(); //continually checks for idle flag state 63 | 64 | if (IdleOnOffFlag == 0 && readytosend == 1) { 65 | Serial.println(); 66 | Serial.println("--Sending Data--"); 67 | //send_data(); 68 | mySerial.write(send_buff[0]); 69 | mySerial.write(send_buff[1]); 70 | 71 | 72 | mySerial.write(send_buff[2]); 73 | 74 | 75 | mySerial.write(send_buff[3]); 76 | 77 | delay(1000); 78 | //readytosend = 0; 79 | 80 | } 81 | 82 | } 83 | 84 | void send_data() { 85 | 86 | if (send_buff_ptr == 0) { 87 | delayMicroseconds(256); 88 | Serial.println("Arbitration Delay 256us"); 89 | } 90 | 91 | Serial.print("Sending Byte #"); 92 | Serial.println(send_buff[send_buff_ptr]); 93 | mySerial.write(send_buff[send_buff_ptr]); 94 | 95 | //delayMicroseconds(2000); //delay between send and receive 96 | 97 | ccd_buff[ccd_buff_ptr] = mySerial.read(); 98 | Serial.print("Got CCD Byte #"); 99 | Serial.println(ccd_buff[ccd_buff_ptr]); 100 | 101 | 102 | if (send_buff_ptr >= 0 && send_buff[send_buff_ptr] != ccd_buff[ccd_buff_ptr]) { 103 | Serial.println("Buffer Mismatch - Aborting"); 104 | Serial.println("EOM Delay"); 105 | delayMicroseconds(1280); //EOM software delay 106 | data_reset(); 107 | return; 108 | } 109 | 110 | 111 | 112 | if (send_buff[send_buff_ptr] == ccd_buff[ccd_buff_ptr] && send_buff_ptr <= 3) { 113 | Serial.println("Successful. Attempting next byte."); 114 | ccd_buff_ptr++; 115 | send_buff_ptr++; 116 | return; 117 | } 118 | 119 | if (send_buff_ptr >= 4) { 120 | data_reset(); 121 | } 122 | } 123 | 124 | 125 | 126 | void data_reset() { 127 | Serial.println("Resetting system"); 128 | 129 | /* 130 | if (ccd_buff_ptr >= 1) { 131 | readytosend = 0; 132 | for (ccd_buff_ptr = 0; ccd_buff_ptr <= 4; ccd_buff_ptr++) { 133 | ccd_buff[ccd_buff_ptr] = 0; 134 | } 135 | 136 | for (send_buff_ptr = 0; send_buff_ptr <= 4; send_buff_ptr++) { 137 | send_buff[send_buff_ptr] = 0; 138 | } 139 | } 140 | */ 141 | ccd_buff_ptr = 0; 142 | send_buff_ptr = 0; 143 | delay(100); 144 | 145 | 146 | } 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /Arduino:328P Sketches/CCDArduino328pUARTAlpineControlExtOsc/CCDArduino328pUARTAlpineControlExtOsc.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Alpine Signaling and Code from mp3car.com - http://www.mp3car.com/vbulletin/input-devices/131147-need-alpine-wired-remote-control-pinout-2.html#post1341875 4 | 5 | Utilizes standard 3 wire 3.5mm connection for the Head Unit. Uses tip and base conductors. Use 220ohm resistor on signal connection to prevent too much current draw at Arduino Pin. 6 | CCD communcation via CDP68HC68S1 7 | 8 | Code adapted from Chris O. and Juha Niinikoski 9 | 10 | -ZJ Steering Control Layout- 11 | 12 | Right Up - VOL UP 13 | Right Down - VOL DOWN 14 | Left Up - NEXT TRACK 15 | Left Down - PREVIOUS TRACK 16 | Left Middle - PRESET/ALBUM UP (actually goes down in the A-Z list.) 17 | 18 | 19 | */ 20 | 21 | //--------------------------Pin Assignment and Binary Coding for Alpine headunit-----------------------// 22 | #define alpPin 4 23 | #define idlePin 2 24 | #define controlPin 3 25 | #define ledPin 13 26 | 27 | boolean volUp[48] = {1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1}; 28 | boolean volDn[48] = {1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1}; 29 | //boolean mute[48] = {1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1}; 30 | boolean pstUp[48] = {1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1}; 31 | boolean trkUp[48] = {1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1}; 32 | boolean trkDn[48] = {1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1}; 33 | //boolean entPlay[48] = {1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; 34 | 35 | 36 | /*****************************************************************************************************/ 37 | // Not in use / This function is performed by hardware Oscillator. 38 | // 1MHz generator for CDP68HC68S1 IC 39 | /*****************************************************************************************************/ 40 | /* 41 | #include //https://pjrc.com/teensy/td_libs_TimerOne.html 42 | const int PWMPin = 9; //PWM~ Pin# 43 | const int Period = 1; // Period 1 us = 1Mhz, 2 us = 500 kHz, 3 us = 333 kHz, 40 us = 25 kHz 44 | const int dutyCycle = 512; // 0 - 1023 512 = dutyCycle 50 45 | */ 46 | /* Download: Included with the Teensyduino Installer 47 | Latest TimerOne on Github https://github.com/PaulStoffregen/TimerOne 48 | Latest TimerThree on Github https://github.com/PaulStoffregen/TimerThree 49 | Hardware Requirements 50 | These libraries use Timer1 and Timer3. 51 | Each timer controls PWM pins. While uses these libraries, analogWrite() to those pins will not work normally, 52 | but you can use the library pwm() function. 53 | Board ------ TimerOne PWM Pins 54 | Teensy 3.1 ------- 3, 4 55 | Teensy 3.0 ------- 3, 4 56 | Teensy 2.0 ------- 4, 14, 15 57 | Teensy++ 2.0 ----- 25, 26, 27 58 | Arduino Uno ------ 9, 10 59 | Arduino Leonardo - 9, 10, 11 60 | Arduino Mega ----- 11, 12, 13 61 | Wiring-S --------- 4, 5 62 | Sanguino --------- 12, 13 63 | Board ------ TimerThree PWM Pins 64 | Teensy 3.1 ------- 25, 32 65 | Teensy 2.0 ------- 9 66 | Teensy++ 2.0 ----- 14, 15, 16 67 | Arduino Leonardo - 5 68 | Arduino Mega ----- 2, 3, 5 69 | / 1MHz generator */ 70 | 71 | 72 | 73 | const int numOfBytes = 8; // receive buffer size 74 | /* //left over from testing. 75 | int timeout = 4; // Serial1.setTimeout(timeout); 76 | volatile int BCounter = 0;// Software UART byte count 77 | */ 78 | 79 | 80 | #include 81 | #include 82 | 83 | 84 | //byte ISR_ccd_buff[numOfBytes]; /* CCD receive buffer inside ISR / MAX Bytes are in numOfBytes */ 85 | byte ccd_buff[numOfBytes]; /* CCD receive buffer / MAX Bytes are in numOfBytes */ 86 | int ccd_buff_ptr; /* CCD receive buffer pointer */ 87 | volatile byte IdleOnOffFlag = 0; //variable for the idle pin. Must be volatile due to being part of interrupt 88 | //boolean DataComplete = false; //variable for declaring end of message string. Can be True or False. 89 | 90 | 91 | AltSoftSerial mySerial; // RX, TX 92 | 93 | void watchdogSetup() { 94 | cli(); // disable all interrupts 95 | wdt_reset(); // reset the WDT timer 96 | WDTCSR |= (1 << WDCE) | (1 << WDE); 97 | WDTCSR = (0 << WDIE) | (1 << WDE) | (0 << WDP3) | (1 << WDP2) | (1 << WDP1) | (0 << WDP0); //1000ms WDT timer 98 | sei(); 99 | } 100 | 101 | void setup() { 102 | watchdogSetup(); 103 | 104 | 105 | pinMode(idlePin, INPUT); //set idle pin for input 106 | //pinMode(controlPin, INPUT); //set control pin for input 107 | pinMode(ledPin, OUTPUT); //prep builtin led pin 108 | pinMode(alpPin, OUTPUT); //Alpine control pin 109 | 110 | 111 | digitalWrite(ledPin, LOW); //Set LED to low once. May be unnecessary but doesn't hurt anything. 112 | 113 | 114 | /*****************************************************************************************************/ 115 | // Not in use / This function is performed by hardware Oscillator. 116 | // 1MHz generator for CDP68HC68S1 IC 117 | /*****************************************************************************************************/ 118 | /* 119 | pinMode(PWMPin, OUTPUT); //prepare pin 9 for clock output 120 | // setup 1MHz generator for CDP68HC68S1 IC 121 | Timer1.initialize(Period); 122 | Timer1.pwm(PWMPin, dutyCycle); ////PWM~ Pin# 10 123 | */ 124 | 125 | 126 | mySerial.begin(7812.5); //for serial IC 127 | //Serial.begin(57600); 128 | 129 | 130 | attachInterrupt(digitalPinToInterrupt(idlePin), endofstring, CHANGE); 131 | // high = BUSY , low = IDLE 132 | } 133 | 134 | 135 | void endofstring() { 136 | IdleOnOffFlag = digitalRead(idlePin); 137 | //IdleOnOffFlag = 1; //Sets flag high when idle pin goes high 138 | 139 | } 140 | 141 | 142 | /* ###################### (CRC) function #######################*/ 143 | uint8_t CyclicRedundancyCheck() { 144 | 145 | //Serial.println("CRC Function"); 146 | // Cyclic Redundancy Check (CRC) 147 | // The checksum byte is calulated by summing all the ID and Data Bytes. 148 | // 256 is then subtracted from that sum. 149 | // The subtraction will end once the checksum falls within 0-255 decim 150 | 151 | 152 | if (ccd_buff_ptr >= 1) { //do not subtract if 0 ( BUG FIX ) 153 | ccd_buff_ptr = ccd_buff_ptr - 1; // subtract 1 from byte count [array indices usually start at 0] 154 | } 155 | uint16_t _CRC = 0; //was uint8_t _CRC = 0; bug fix 156 | for (uint16_t CRCptr = 0; CRCptr < ccd_buff_ptr; CRCptr ++) { // uint16_t 0 to 65,535 ~ int16_t -32,768 to 32,767 157 | _CRC = _CRC + ccd_buff[CRCptr]; 158 | } 159 | while (_CRC > 255) { 160 | _CRC = _CRC - 256; 161 | } 162 | uint8_t x = _CRC; 163 | return x; 164 | } 165 | 166 | 167 | void loop() { 168 | // put your main code here, to run repeatedly: 169 | wdt_reset(); 170 | 171 | //IdleOnOffFlag = digitalRead(idlePin); 172 | 173 | 174 | while (mySerial.available()) { 175 | ccd_buff[ccd_buff_ptr] = mySerial.read(); 176 | //ccd_buff[ccd_buff_ptr] = data; // read & store character 177 | ccd_buff_ptr++; // increment the pointer to the next byte 178 | } 179 | 180 | 181 | if (IdleOnOffFlag == 0) { // check the CDP68HC68S1 IDLE pin interrupt flag, change from Low to High. 182 | 183 | 184 | // Serial-x.readBytes(buffer, length) 185 | // Serial-x.readBytes() reads Bytes from the serial port into a buffer. 186 | // The function terminates if the determined length has been read, or it times out (see Serial.setTimeout()). 187 | // Serial.readBytes() returns the number of characters placed in the buffer. A 0 means no valid data was found. 188 | 189 | uint8_t CRC = 0; 190 | CRC = CyclicRedundancyCheck(); // Go get CRC. 191 | 192 | if (CRC != 0) { 193 | //Serial.print("CRC = #"); //Debug Serial prints 194 | //Serial.println(CRC); 195 | //Serial.print("CCD Pointer="); 196 | //Serial.println(ccd_buff_ptr); 197 | if (ccd_buff[ccd_buff_ptr] == CRC && ccd_buff_ptr != 0) { 198 | //Serial.println("Process"); 199 | noInterrupts(); // Disables interrupts 200 | process_data(); // GOTO process_data loop 201 | ccd_buff_ptr = 0; // RESET buffer pointer to byte 0 for data to be overwritten 202 | interrupts(); 203 | } 204 | } 205 | 206 | } 207 | 208 | } 209 | 210 | 211 | 212 | void process_data() { 213 | 214 | 215 | switch (ccd_buff[0]) // decide what to do from first byte / ID BYTE 216 | { 217 | case 0x82: // Do Radio/VIC Time Commands = 130 DEC 218 | 219 | 220 | if ((ccd_buff[1] == 0x20) && (ccd_buff[2] == 0x20) && (ccd_buff[3] == 0x00) && (ccd_buff[4] == 0xC2)) { 221 | //VOLUME UP 222 | volUpSend(); 223 | break; 224 | } 225 | 226 | 227 | if ((ccd_buff[1] == 0x20) && (ccd_buff[2] == 0x40) && (ccd_buff[3] == 0x00) && (ccd_buff[4] == 0xE2)) { 228 | //VOLUME DOWN 229 | volDnSend(); 230 | break; 231 | } 232 | 233 | 234 | if ((ccd_buff[1] == 0x20) && (ccd_buff[2] == 0x04) && (ccd_buff[3] == 0x00) && (ccd_buff[4] == 0xA6)) { 235 | //TRACK UP 236 | trkUpSend(); 237 | break; 238 | } 239 | 240 | 241 | if ((ccd_buff[1] == 0x20) && (ccd_buff[2] == 0x08) && (ccd_buff[3] == 0x00) && (ccd_buff[4] == 0xAA)) { 242 | //TRACK DOWN 243 | trkDnSend(); 244 | break; 245 | } 246 | 247 | 248 | if ((ccd_buff[1] == 0x20) && (ccd_buff[2] == 0x00) && (ccd_buff[3] == 0x01) && (ccd_buff[4] == 0xA3)) { 249 | //ALBUM UP 250 | pstUpSend(); 251 | break; 252 | } 253 | default: 254 | //do nothing 255 | break; 256 | } 257 | /*ccd_buff[0] = 0; 258 | ccd_buff[1] = 0; 259 | ccd_buff[2] = 0; 260 | ccd_buff[3] = 0; 261 | ccd_buff[4] = 0; 262 | ccd_buff[5] = 0;*/ 263 | 264 | } 265 | 266 | 267 | //---------VOL UP----------------------------------------------- 268 | void volUpSend() { 269 | digitalWrite(ledPin, HIGH); 270 | //first send 8ms high 271 | digitalWrite(alpPin, HIGH); 272 | delayMicroseconds(8000); // New 8ms Delay 273 | // send 4.5ms low 274 | digitalWrite(alpPin, LOW); 275 | delayMicroseconds(4500); 276 | 277 | 278 | for (int i = 0; i <= 47; i++) { 279 | //send bit for 0.5ms 280 | if (volUp[i] == 1 ) { 281 | digitalWrite(alpPin, HIGH); 282 | } else { 283 | digitalWrite(alpPin, LOW); 284 | } 285 | delayMicroseconds(500); 286 | // wait 0.5ms 287 | digitalWrite(alpPin, LOW); 288 | delayMicroseconds(500); 289 | } 290 | // send 41ms low 291 | digitalWrite(alpPin, LOW); 292 | for (unsigned int i = 0; i <= 40; i++) { //New 41ms Delay 293 | delayMicroseconds(1000); 294 | } 295 | digitalWrite(ledPin, LOW); 296 | } 297 | 298 | 299 | //---------VOL DOWN----------------------------------------------- 300 | void volDnSend() { 301 | digitalWrite(ledPin, HIGH); 302 | //first send 8ms high 303 | digitalWrite(alpPin, HIGH); 304 | delayMicroseconds(8000); // New 8ms Delay 305 | // send 4.5ms low 306 | digitalWrite(alpPin, LOW); 307 | delayMicroseconds(4500); 308 | 309 | 310 | for (int i = 0; i <= 47; i++) { 311 | //send bit for 0.5ms 312 | if (volDn[i] == 1 ) { 313 | digitalWrite(alpPin, HIGH); 314 | } else { 315 | digitalWrite(alpPin, LOW); 316 | } 317 | delayMicroseconds(500); 318 | // wait 0.5ms 319 | digitalWrite(alpPin, LOW); 320 | delayMicroseconds(500); 321 | } 322 | // send 41ms low 323 | digitalWrite(alpPin, LOW); 324 | for (unsigned int i = 0; i <= 40; i++) { //New 41ms Delay 325 | delayMicroseconds(1000); 326 | } 327 | digitalWrite(ledPin, LOW); 328 | } 329 | 330 | 331 | //---------Next Track----------------------------------------------- 332 | void trkUpSend() { 333 | digitalWrite(ledPin, HIGH); 334 | //first send 8ms high 335 | digitalWrite(alpPin, HIGH); 336 | delayMicroseconds(8000); // New 8ms Delay 337 | // send 4.5ms low 338 | digitalWrite(alpPin, LOW); 339 | delayMicroseconds(4500); 340 | 341 | 342 | for (int i = 0; i <= 47; i++) { 343 | //send bit for 0.5ms 344 | if (trkUp[i] == 1 ) { 345 | digitalWrite(alpPin, HIGH); 346 | } else { 347 | digitalWrite(alpPin, LOW); 348 | } 349 | delayMicroseconds(500); 350 | // wait 0.5ms 351 | digitalWrite(alpPin, LOW); 352 | delayMicroseconds(500); 353 | } 354 | // send 41ms low 355 | digitalWrite(alpPin, LOW); 356 | for (unsigned int i = 0; i <= 40; i++) { //New 41ms Delay 357 | delayMicroseconds(1000); 358 | } 359 | digitalWrite(ledPin, LOW); 360 | } 361 | 362 | 363 | //---------Previous Track---------------------------------------------- 364 | void trkDnSend() { 365 | digitalWrite(ledPin, HIGH); 366 | //first send 8ms high 367 | digitalWrite(alpPin, HIGH); 368 | delayMicroseconds(8000); // New 8ms Delay 369 | // send 4.5ms low 370 | digitalWrite(alpPin, LOW); 371 | delayMicroseconds(4500); 372 | 373 | 374 | for (int i = 0; i <= 47; i++) { 375 | //send bit for 0.5ms 376 | if (trkDn[i] == 1 ) { 377 | digitalWrite(alpPin, HIGH); 378 | } else { 379 | digitalWrite(alpPin, LOW); 380 | } 381 | delayMicroseconds(500); 382 | // wait 0.5ms 383 | digitalWrite(alpPin, LOW); 384 | delayMicroseconds(500); 385 | } 386 | // send 41ms low 387 | digitalWrite(alpPin, LOW); 388 | for (unsigned int i = 0; i <= 40; i++) { //New 41ms Delay 389 | delayMicroseconds(1000); 390 | } 391 | digitalWrite(ledPin, LOW); 392 | } 393 | 394 | 395 | //---------NEXT DOWN---------------------------------------------- 396 | void pstUpSend() { 397 | digitalWrite(ledPin, HIGH); 398 | //first send 8ms high 399 | digitalWrite(alpPin, HIGH); 400 | delayMicroseconds(8000); // New 8ms Delay 401 | // send 4.5ms low 402 | digitalWrite(alpPin, LOW); 403 | delayMicroseconds(4500); 404 | 405 | 406 | for (int i = 0; i <= 47; i++) { 407 | //send bit for 0.5ms 408 | if (pstUp[i] == 1 ) { 409 | digitalWrite(alpPin, HIGH); 410 | } else { 411 | digitalWrite(alpPin, LOW); 412 | } 413 | delayMicroseconds(500); 414 | // wait 0.5ms 415 | digitalWrite(alpPin, LOW); 416 | delayMicroseconds(500); 417 | } 418 | // send 41ms low 419 | digitalWrite(alpPin, LOW); 420 | for (unsigned int i = 0; i <= 40; i++) { //New 41ms Delay 421 | delayMicroseconds(1000); 422 | } 423 | digitalWrite(ledPin, LOW); 424 | } 425 | --------------------------------------------------------------------------------