Monday, August 26, 2013

Updated BOM


Qty
Value Device Package Parts Description
3
LED5MM LED5MM LED1, LED2, POWER LED
6
PINHD-1X1 1X01 +5V, GND, LIN, RIN, RX, TX PIN HEADER
1 .1uF C-US025-025X050 C025-025X050 C2 CAPACITOR, American symbol
1 0.1uF C-US025-025X050 C025-025X050 C1 CAPACITOR, American symbol
4 100nF C-US025-025X050 C025-025X050 C3, C4, C5, C6 CAPACITOR, American symbol
1 10K R-US_0207/10 0207/10 R5 RESISTOR, American symbol
2 10K R-US_0207/2V 0207/2V R4, R6 RESISTOR, American symbol
4 10uF C-EU025-030X050 C025-030X050 C11, C12, C13, C14 CAPACITOR, European symbol
2 10uF CPOL-EUE2.5-5 E2,5-5 C9, C10 POLARIZED CAPACITOR, European symbol
1 1N4007-01 1N4007-01 D01B D1 1N4007/SM4007: General purpose silicon diode
1 1uF CPOL-EUE2.5-5 E2,5-5 C8 POLARIZED CAPACITOR, European symbol
3 330R R-US_0207/2V 0207/2V R1, R2, R3 RESISTOR, American symbol
1 470nF C-US025-025X050 C025-025X050 C7 CAPACITOR, American symbol
1 7805 78XXS 78XXS IC4 VOLTAGE REGULATOR
1 827229-1 827229-1 827229-1 U$5
2 DRV134PA DRV134PA DIL08 U$3, U$4 Audio Balanced Line Drivers
1 FTDI_1-6 FTDI_BASICPTH FTDI_BASIC JP1 FTDI Basic: 3.3V and 5V
1 LTC1144 LTC1144 DIP08L-SETH N1 LTC1144: Switched capacitor voltage converter (Linear Technology)
1 MCP2515-E/P MCP2515-E/P DIL18 IC1
1 MEGA8-P MEGA8-P DIL28-3-SETH IC3 MICROCONTROLLER
2 RESONATORPTH RESONATORPTH RESONATOR-PTH U$1, U$2 Resonator
1 SN65HVD251P SN65HVD251P DIL08 IC2

Tuesday, August 13, 2013

New module

Possible new version of BlueSaab :)

This one only has a 3.5mm stereo plug for audio...working on an ethernet jack or something like that...



Wednesday, August 7, 2013

Contact Info

I love helping people figure things out so they can be more self-sufficient.

If anyone has any questions, I'll be more than happy to try and answer them.

I can be reached at se4587 at oohay (backwards).com. Same thing at gmail but I don't check/use it as often.

I only had 1 person actually purchase the old cut-crimp method of wiring up a unit, so i'm curious how many people would be interested in this new version...? I see that one guy is still interested in steering wheel ipod controls :) Like I said, that feature is still there, it just needs to be wired up to an ipod connector.

Tuesday, August 6, 2013

New PCB & code

So I did some more redesigning and played with the code again. I moved away from the priority SID text because it prevented my Night Panel from working.

Here's a link to my public OSHPark.com profile. You can order PCBs (in multiples of 3) for ~$30, shipped. They're excellent quality. I'll get some pictures up soon of a newly finished board.

Also, this version uses the original CD Changer harness plug so no more splicing wires!! Literally, plug-n-play.

So right now there are several options. The board & code still supports iPod steering wheel controls, but it doesn't sound like many people need/care/want that. I'm not going to remove that, but it sounds like most people just want an audio source, and a universal one at that.

I can just put a 3.5mm stereo jack in the case and you can run a long 3.5mm male to male cable from the trunk to the dash (under the door sills and such). This should work pretty well.

Or one could install a bluetooth module in the unit, much like my car does. I made sure there were 5v and GND pins available in case anyone wanted to power a bluetooth module up.

// ----------------------------------------------
// SECUDUINO
// http://secuduino.blogspot.com/
// By Igor Real
// 16/05/2011
//
// Saab CDC Changer Emulator
// http://BlueSaab.blogspot.com/
// By Seth Evans
// 29 July 2013
// ----------------------------------------------

#include <CAN.h>

int cdbutton = 0;
int toggleshuffle = 1;
int mute = 0;
int CDCcmd[] = {
  0xE0,0x00,0x3F,0x31,0xFF,0xFF,0xFF,0xD0};
int ninefivecmd[] = {
  0x62,0x00,0x00,0x16,0x01,0x02,0x00,0x00};
int beep[] = {
  0x80,0x04,0x00,0x00,0x00,0x00,0x00,0x00};
int playipod[] = {
  0xFF,0x55,0x04,0x02,0x00,0x00,0x01,0xF9};
int playpauseipod[] = {
  0xFF,0x55,0x03,0x02,0x00,0x01,0xFA};
int stopipod[] = {
  0xFF,0x55,0x04,0x02,0x00,0x00,0x02,0xF8};
int next[] = {
  0xFF,0x55,0x03,0x02,0x00,0x08,0xF3};
int prev[] = {
  0xFF,0x55,0x03,0x02,0x00,0x10,0xEB};
int shuffle[] = {
  0xFF,0x55,0x04,0x02,0x00,0x00,0x80,0x7A};
int repeat[] = {
  0xFF,0x55,0x05,0x02,0x00,0x00,0x00,0x01,0xF8};
int buttonRelease[] = {
  0xFF,0x55,0x03,0x02,0x00,0x00,0xFB};

void setup() {
  // set up CAN
  CAN.begin(47);  // Saab I-Bus is 47.619kbps
  Serial.begin(9600);
  //cdbutton = 0;
  //toggleshuffle = 1;
  CAN_TxMsg.header.rtr=0;     // this value never changes
  CAN_TxMsg.header.length=8;  // this value never changes
  // not sure if this is needed; pauses program before it loops
  Serial.println("9-5 Test Code 2");
  delay(2000);
}

void loop() {
  //cdbutton = 1;
  //PrintBus();
  // CDC code needs sent every second or less so all loops
  // running added together need to take less than 1000ms
  // but no more or the car won't "see" the CDC
  CDC();
  for (int i = 0; i <= 860; i++) {
    if (CAN.CheckNew()) {
      CAN_TxMsg.data[0]++;
      CAN.ReadFromDevice(&CAN_RxMsg);
      //PrintBus();
      if (CAN_RxMsg.id==0x6A1) {
        CAN_TxMsg.id=0x6A2;     // CD Changer
        for (int c = 0; c < 8; c++) {
          CAN_TxMsg.data[c]=ninefivecmd[c];
        }
        CAN.send(&CAN_TxMsg);
      }

      if (CAN_RxMsg.id==0x3C0) {
        if (CAN_RxMsg.data[0]==0x80) {
          switch (CAN_RxMsg.data[1]) {
          case 0x24:
            cdbutton = 1;
            for (int j = 0; j < 8; j++) {
              CAN_TxMsg.id=0x430;
              CAN_TxMsg.data[j]=beep[j];
            }
            CAN.send(&CAN_TxMsg);
            for (int j = 0; j < 8; j++) {
              Serial.write(byte(playipod[j]));
            }
            delay(3);
            //Serial.println("Release");
            for (int i = 0; i < 7; i++) {
              Serial.write(byte(buttonRelease[i]));
            }
            break;
          case 0x14:
            cdbutton = 0;  
            for (int a = 0; a <=2; a++) {
              for (int j = 0; j < 8; j++) {
                CAN_TxMsg.id=0x430;
                CAN_TxMsg.data[j]=beep[j];
              }
              CAN.send(&CAN_TxMsg);
            }
            for (int j = 0; j < 8; j++) {
              Serial.write(byte(stopipod[j]));
            }
            delay(3);
            //Serial.println("Release");
            for (int i = 0; i < 7; i++) {
              Serial.write(byte(buttonRelease[i]));
            }
            //Serial.println("Radio");
            break;
          }
          if (cdbutton == 1) {
            switch (CAN_RxMsg.data[1]) {
            case 0x59: // NXT button signal
              for (int j = 0; j < 7; j++) {
                Serial.write(byte(playpauseipod[j]));
              }
              break;
            case 0x76: // Long press of CD/RDM button
              if (toggleshuffle > 3) {
                toggleshuffle = 1;
              }
              switch (toggleshuffle) {
              case 1:
                for (int j = 0; j < 9; j++) {
                  Serial.write(byte(repeat[j]));
                }
                break;
              case 2:
                for (int j = 0; j < 9; j++) {
                  Serial.write(byte(repeat[j]));
                }
                break;
              case 3:
                for (int j = 0; j < 9; j++) {
                  Serial.write(byte(repeat[j]));
                }
                for (int j = 0; j < 8; j++) {
                  Serial.write(byte(shuffle[j]));
                }
                break;
              }
              toggleshuffle++;
              //break;
            case 0xB1: // Audio mute on?
              for (int j = 0; j < 8; j++) {
                Serial.write(byte(stopipod[j]));
              }
              break;
            case 0xB0: // Audio mute off?
              for (int j = 0; j < 8; j++) {
                Serial.write(byte(playipod[j]));
              }
              break;
            case 0x35: // Seek next (Seek+)?
              for (int j = 0; j < 7; j++) {
                Serial.write(byte(next[j]));
              }
              break;
            case 0x36: // Seek previous (Seek-)?
              for (int j = 0; j < 7; j++) {
                Serial.write(byte(prev[j]));
              }
              break;
            }
            delay(3);
            //Serial.println("Release");
            for (int i = 0; i < 7; i++) {
              Serial.write(byte(buttonRelease[i]));
            }
          }
        }
      }
      if (CAN_RxMsg.id==0x290) {
        if (CAN_RxMsg.data[0]==0x80) {
          if (cdbutton == 1) {
            switch (CAN_RxMsg.data[2]) {
              //case 0x04: // NXT button on wheel
              //for (int j = 0; j < 9; j++) {
              //Serial.write(byte(repeat[j]));
              //}
              //break;
            case 0x10: // Seek+ button on wheel
              //Serial.println("Next");
              for (int j = 0; j < 7; j++) {
                Serial.write(byte(next[j]));
              }
              break;
            case 0x08: // Seek- button on wheel
              //Serial.println("Prev");
              for (int k = 0; k < 7; k++) {
                Serial.write(byte(prev[k]));
              }
              break;
            }
            delay(3);
            //Serial.println("Release");
            for (int i = 0; i < 7; i++) {
              Serial.write(byte(buttonRelease[i]));
            }
          }
        }
      }
    }
    delay(1);
  }
  if (cdbutton==1) {
    //Serial.println("iPod ON");
    iPodOn();
  }
  else {
    //Serial.println("iPod OFF");
    //iPodOff();
    //delay(400);
  }
}

void CDC() {
  CAN_TxMsg.id=0x3C8;     // CD Changer
  for (int c = 0; c < 8; c++) {
    CAN_TxMsg.data[c]=CDCcmd[c];
  }
  CAN.send(&CAN_TxMsg);
}

void iPodOn() {
  // This loop takes 50ms
  CAN_TxMsg.id=0x328;     // SID audio text
  CAN_TxMsg.data[0]=0x42; // message 2
  CAN_TxMsg.data[1]=0x96;
  CAN_TxMsg.data[2]=0x02; // Row 2
  CAN_TxMsg.data[3]=0x20; // _
  CAN_TxMsg.data[4]=0x3C; // <
  CAN_TxMsg.data[5]=0x42; // B
  CAN_TxMsg.data[6]=0x6C; // l
  CAN_TxMsg.data[7]=0x75; // u
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.data[0]=0x01; // message 1
  CAN_TxMsg.data[3]=0x65; // e
  CAN_TxMsg.data[4]=0x74; // t
  CAN_TxMsg.data[5]=0x6F; // o
  CAN_TxMsg.data[6]=0x6F; // o
  CAN_TxMsg.data[7]=0x74; // t
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.data[0]=0x00; // message 0
  CAN_TxMsg.data[3]=0x68; // h
  CAN_TxMsg.data[4]=0x3E; // >
  CAN_TxMsg.data[5]=0x20; //
  CAN_TxMsg.data[6]=0x20; //
  CAN_TxMsg.data[7]=0x20; //
  CAN.send(&CAN_TxMsg);
  delay(10);

  CAN_TxMsg.id=0x348;     // audio text control
  CAN_TxMsg.data[0]=0x11; // 11
  CAN_TxMsg.data[1]=0x02; // Row 2?
  CAN_TxMsg.data[2]=0x05; // 05
  CAN_TxMsg.data[3]=0x18; // priority 18?
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(10);

  /*CAN_TxMsg.id=0x368;     // SID text priority
   CAN_TxMsg.data[0]=0x02; // Row 2
   CAN_TxMsg.data[1]=0x18; // priority 18?
   CAN_TxMsg.data[2]=0x00;
   CAN_TxMsg.data[3]=0x00;
   CAN_TxMsg.data[4]=0x00;
   CAN_TxMsg.data[5]=0x00;
   CAN_TxMsg.data[6]=0x00;
   CAN_TxMsg.data[7]=0x00;
   CAN.send(&CAN_TxMsg);
   delay(10);
   */
}

void PrintBus() {
  if (CAN_RxMsg.id==0x6A2) {
  //if (CAN_RxMsg.data[0]==0x80) {
    Serial.print(CAN_RxMsg.id,HEX);
    Serial.print(";");
    for (int i = 0; i < 8; i++) {
      Serial.print(CAN_RxMsg.data[i],HEX);
      Serial.print(";");
    }
    Serial.println("");
  }
}