Advertisement
Guest User

Untitled

a guest
Jan 28th, 2018
260
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.72 KB | None | 0 0
  1. /*----------------------------------------------------------------------------------------------------------------------------------
  2.  *  Name          :   AuxRancher.ino
  3.  *  Description   :   I hope this works and can talk to the CN702 12 pin jack
  4.  *  MCU           :   Arduino Nano from Banggood lol
  5.  *  Author        :   Bo Laurence Thompson
  6.  *  History       :   2016-01-23 - v0.1 Prototyping draft heavily inspired by thew work of Louis Frigon, aka(?) SigmaObjects.
  7.  *  
  8.  *  
  9. # DON'T BE A DICK PUBLIC LICENSE
  10.  
  11. > Version 1.1, December 2016
  12.  
  13. > Copyright (C) [year] [fullname]
  14.  
  15. Everyone is permitted to copy and distribute verbatim or modified
  16. copies of this license document.
  17.  
  18. > DON'T BE A DICK PUBLIC LICENSE
  19. > TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  20.  
  21. 1. Do whatever you like with the original work, just don't be a dick.
  22.  
  23.    Being a dick includes - but is not limited to - the following instances:
  24.  
  25.  1a. Outright copyright infringement - Don't just copy this and change the name.
  26.  1b. Selling the unmodified original with no work done what-so-ever, that's REALLY being a dick.
  27.  1c. Modifying the original work to contain hidden harmful content. That would make you a PROPER dick.
  28.  
  29. 2. If you become rich through modifications, related works/services, or supporting the original work,
  30. share the love. Only a dick would make loads off this work and not buy the original work's
  31. creator(s) a pint.
  32.  
  33. 3. Code is provided with no warranty. Using somebody else's code and bitching when it goes wrong makes
  34. you a DONKEY dick. Fix the problem yourself. A non-dick would submit the fix back.
  35.  
  36.  
  37.  ---------------------------------------------------------------------------------------------------------------------------------*/
  38. #include <avr/wdt.h>
  39.  
  40. #define fwVer                 "v0.1"
  41. #define fwDt                  __DATE__
  42.  
  43. #define ZERO_LENGTH           65
  44. #define ONE_LENGTH            38
  45. #define BIT_LENGTH            76
  46. #define START_BIT_ON_LENGTH   345
  47. #define START_BIT_LENGTH      382
  48. #define MSG_NORMAL            1
  49. #define MSG_BCAST             0
  50.  
  51.  
  52. #define HU_ADDR                 0x190
  53. #define ALL_AUDIO_ADDR          0x1FF
  54. #define MY_ADDR                 0x360
  55. #define UNKNOWN_ADDR            0xFFF
  56.  
  57. #define DESCRIPTION_LENGTH      20
  58.  
  59.  
  60. bool ParityBit;
  61. bool bbit;
  62. word mAddr;
  63. word sAddr;
  64. byte cBits;
  65. byte dlnth;
  66. byte data[256];
  67. char descBuf[DESCRIPTION_LENGTH+1];
  68.  
  69. typedef byte MessageID;
  70. enum {
  71.   ACT_UNKNOWN,
  72.   ACT_POWERON,
  73.   ACT_POWEROFF,
  74.   ACT_PASSIVEOFF_0,
  75.   ACT_PASSIVEOFFRARE_0,
  76.   ACT_PASSIVEONRARE,
  77.   ACT_PASSIVEON_0,
  78.   ACT_PRESSDISC,
  79.   ACT_PRESSAM,
  80.   ACT_STATIONFOUND,
  81.   ACT_INIT,
  82.   ACT_AM
  83. };
  84.  
  85. struct MessageDef {
  86.   MessageID ID;
  87.   word MasterAddr;
  88.   word SlaveAddr;
  89.   byte PayloadLength;
  90.   word Payload[24];
  91.   char Description[DESCRIPTION_LENGTH];
  92. };
  93.  
  94. const MessageDef MessageTable[] PROGMEM = {
  95.   {ACT_POWERON,           HU_ADDR, ALL_AUDIO_ADDR, 13,  {0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x00, 0x81, 0x100, 0x01, 0xF1, 0x31, 0x60},                    "FM in use"},
  96.   {ACT_POWEROFF,          HU_ADDR, UNKNOWN_ADDR, 13,    {0x00, 0x60, 0x31, 0xF1, 0x00, 0x00, 0x81, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00},                       "off?"},
  97.   {ACT_PASSIVEOFF_0,      HU_ADDR, UNKNOWN_ADDR, 3,     {0x46, 0x01, 0x11},                                                                                   "Passive: Weak"},
  98.   {ACT_PASSIVEOFFRARE_0,  HU_ADDR, UNKNOWN_ADDR, 4,     {0x60, 0x45, 0x01, 0x11},                                                                             "Passive: Strong"},
  99.   {ACT_PASSIVEONRARE,     HU_ADDR, UNKNOWN_ADDR, 4,     {0x100, 0x20, 0x01, 0x11},                                                                            "Passive: Fierce"},
  100.   {ACT_PASSIVEON_0,       HU_ADDR, ALL_AUDIO_ADDR, 16,  {0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x100, 0x80, 0xF1, 0x31, 0x74},    "Vol Knob"},
  101.   {ACT_PRESSDISC,         HU_ADDR, ALL_AUDIO_ADDR, 4,   {0x00, 0x9F, 0x31, 0x62},                                                                             "No DISC available"},
  102.   {ACT_PRESSAM,           HU_ADDR, ALL_AUDIO_ADDR, 24,  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x00, 0xCB, 0x00, 0xAF, 0x00, 0x69, 0x00, 0x37, 0x00, 0x03, 0x00}, "AM/FM Switch"},
  103.   {ACT_STATIONFOUND,      HU_ADDR, ALL_AUDIO_ADDR, 13,  {0x00, 0x00, 0x00, 0x04, 0x00, 0x100, 0x00, 0x100, 0x100, 0x01, 0xF1, 0x31, 0x60},                     "FM station found"},
  104.   {ACT_INIT,              HU_ADDR, UNKNOWN_ADDR,    3,  {0x100, 0x01, 0x11},                                                                                    "Init"},
  105.   {ACT_AM,                HU_ADDR, ALL_AUDIO_ADDR, 13,  {0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x00, 0x01, 0x01, 0x01, 0xF1, 0x31, 0x60},                        "AM in use"}
  106. };
  107.  
  108. const byte MessageTableSize = sizeof(MessageTable)/sizeof(MessageDef);
  109.  
  110.  
  111. //====================================================================================COPYPASTED
  112. #define DATAIN_PIN              ACSR
  113. #define DATAIN                  ACO
  114.  
  115. #define INPUT_IS_SET            ( bit_is_set( DATAIN_PIN, DATAIN ) )
  116. #define INPUT_IS_CLEAR          ( bit_is_clear( DATAIN_PIN, DATAIN ) )
  117. //===================================================================================WHAT DOES THIS MEAN
  118.  
  119.  
  120.  
  121.  
  122.  
  123. //============================================================================================================================================================================================================
  124. //        
  125. //        
  126. //============================================================================================================================================================================================================
  127. //============================================================================================================================================================================================================
  128. //        Setup()
  129. //        Runs once at PowerOn and whenever Reset is pushed.
  130. //============================================================================================================================================================================================================
  131. void setup() {
  132.   TCCR1A = 0;
  133.   TCCR1B = _BV(CS11);
  134.  
  135.   Serial.begin(9600);
  136.  
  137.   //pinMode(3,INPUT);
  138.   //pinMode(2,INPUT);
  139.   PORTD |= _BV(PD3);   // PD3 (+) high.
  140.   PORTD &= ~_BV(PD2);  // PD2 (-) low.
  141.   pinMode(LED_BUILTIN,OUTPUT);
  142.   //DDRD |= _BV(PD2) | _BV(PD3);
  143.  
  144.   //two second watchdog
  145.   wdt_enable( WDTO_2S );
  146.  
  147.   Serial.println("Toyota AuxRancher");
  148.   Serial.println("By Bo Thompson");
  149.   Serial.println("Firmware "+String(fwVer)+", compiled on "+fwDt);
  150.   Serial.println("Known messages: " +String(MessageTableSize));
  151.  
  152.   LedOff();
  153. }
  154.  
  155.  
  156. //============================================================================================================================================================================================================
  157. //        LedOn() and LedOff()
  158. //        Just manages the Led a bit easier.
  159. //============================================================================================================================================================================================================
  160. void LedOff() {
  161.   digitalWrite(LED_BUILTIN, LOW);
  162. }
  163. void LedOn() {
  164.   digitalWrite(LED_BUILTIN, HIGH);
  165. }
  166.  
  167.  
  168.  
  169. //============================================================================================================================================================================================================
  170. //        
  171. //        
  172. //============================================================================================================================================================================================================
  173. void SetOutputHigh() {
  174.   DDRD |= _BV(PD2) | _BV(PD3);
  175. }
  176. void SetOutputLow() {
  177.   pinMode(3,OUTPUT);
  178.   pinMode(2,INPUT);
  179. }
  180. void ReleaseOutput() {
  181.   DDRD &= ~( _BV(PD2) | _BV(PD3) );
  182.   }
  183. //============================================================================================================================================================================================================
  184. //        Loop()
  185. //        Constantly running.
  186. //============================================================================================================================================================================================================
  187. void loop() {
  188.   wdt_reset();
  189.   /*while (INPUT_IS_CLEAR) wdt_reset();
  190.   TCNT1=0;
  191.   while (INPUT_IS_SET);
  192.   Serial.println(String(TCNT1));*/
  193.  
  194.   if (ReadMessage()==1) {
  195.     byte msgid =IdentifyMessage();
  196.     if (msgid < MessageTableSize) {
  197.       strncpy_P(descBuf, MessageTable[msgid].Description, DESCRIPTION_LENGTH);
  198.       Serial.println(descBuf);
  199.       if (pgm_read_byte_near(&MessageTable[msgid].ID) == ACT_PRESSDISC ){
  200.         SendMessage();
  201.       }
  202.     }
  203.   }
  204. }
  205.  
  206. //============================================================================================================================================================================================================
  207. //        
  208. //        
  209. //============================================================================================================================================================================================================
  210. bool SendMessage() {
  211.   while (!BusIsFree());
  212.   LedOn();
  213.  
  214.   //begin
  215.   SendStartBit();
  216.  
  217.   //broadcast bit
  218.   Send1BitWord(0);
  219.  
  220.   //master address with parity
  221.   Send12BitWord(MY_ADDR);
  222.   Send1BitWord(ParityBit);
  223.  
  224.   //slave address with parity and ack
  225.   Send12BitWord(HU_ADDR);
  226.   Send1BitWord(ParityBit);
  227.   if (!LeadAck()) {
  228.     Serial.println("SendMessage: No Ack at Slave Address!");
  229.     return false;
  230.   }
  231.   else Serial.println("SendMessage: Ack received");
  232.  
  233.   LedOff();
  234.   return true;
  235. }
  236.  
  237. //============================================================================================================================================================================================================
  238. //        
  239. //        
  240. //============================================================================================================================================================================================================
  241. bool BusIsFree() {
  242.   while (INPUT_IS_SET) wdt_reset();
  243.   TCNT1 = 0;
  244.   while (TCNT1<BIT_LENGTH) {
  245.     if (INPUT_IS_SET) return false;
  246.   }
  247.   return true;
  248. }
  249.  
  250. //============================================================================================================================================================================================================
  251. //        
  252. //        
  253. //============================================================================================================================================================================================================
  254. bool LeadAck() {
  255.   TCNT1 = 0;
  256.  
  257.   //drive a one
  258.   DDRD |= _BV(PD2) | _BV(PD3);
  259.   while (TCNT1 < ONE_LENGTH);
  260.   //while (1) wdt_reset();
  261.  
  262.   //now shut up and listen
  263.   DDRD &= ~( _BV(PD2) | _BV(PD3) );
  264.   while(INPUT_IS_SET);
  265.   //if we just waited for a zero length,
  266.   if (TCNT1 > ONE_LENGTH+(ZERO_LENGTH-ONE_LENGTH)/2) {
  267.     return true;
  268.   }
  269.   //otherwise, something is wrong.
  270.   return false;
  271. }
  272. //============================================================================================================================================================================================================
  273. //        
  274. //        
  275. //============================================================================================================================================================================================================
  276. void SendStartBit() {
  277.   TCNT1 = 0;
  278.  
  279.   //drive for the length of the start bit
  280.   DDRD |= _BV(PD2) | _BV(PD3);
  281.   while (TCNT1 < START_BIT_ON_LENGTH);
  282.  
  283.   //pull until the grace period is over
  284.   DDRD &= ~( _BV(PD2) | _BV(PD3) );
  285.   while (TCNT1 < START_BIT_LENGTH);
  286. }
  287. //============================================================================================================================================================================================================
  288. //        
  289. //        
  290. //============================================================================================================================================================================================================
  291. void Send1BitWord(bool data) {
  292.   TCNT1 = 0;
  293.  
  294.   //drive for the length of one or zero
  295.   DDRD |= _BV(PD2) | _BV(PD3);
  296.   if (data) while (TCNT1 < ONE_LENGTH);
  297.   else while(TCNT1 < ZERO_LENGTH);
  298.  
  299.   //pull until the bit is over
  300.   DDRD &= ~( _BV(PD2) | _BV(PD3) );
  301.   while (TCNT1 < BIT_LENGTH);
  302. }
  303.  
  304. //============================================================================================================================================================================================================
  305. //        
  306. //        
  307. //============================================================================================================================================================================================================
  308. void Send12BitWord(word data) {
  309.   ParityBit = 0;
  310.  
  311.   for (byte ii = 0; ii<12; ii++){
  312.     TCNT1 = 0;
  313.     DDRD |= _BV(PD2) | _BV(PD3);
  314.     if (data & 0x0800) {
  315.       ParityBit = !ParityBit;
  316.       while (TCNT1<ONE_LENGTH);
  317.     }
  318.     else {
  319.       while (TCNT1<ZERO_LENGTH);
  320.     }
  321.     DDRD &= ~( _BV(PD2) | _BV(PD3) );
  322.     data<=1;
  323.     while (TCNT1<BIT_LENGTH);
  324.   }
  325. }
  326.  
  327. //============================================================================================================================================================================================================
  328. //        ReadMessage()
  329. //        Returns a boolean, 1 if it works and 0 if there is some kind of error. Usually parity.
  330. //        Also sets the global variables for the message information read.
  331. //        Happens once per loop.
  332. //============================================================================================================================================================================================================
  333. bool ReadMessage() {
  334.  
  335.   //start bit
  336.   ReadBits(1);
  337.   LedOn();
  338.  
  339.   //broadcast bit
  340.   bbit = ReadBits(1);
  341.  
  342.  
  343.   //master address
  344.   mAddr = ReadBits(12);
  345.   //handle parity
  346.   if (ParityBit!=ReadBits(1)){
  347.     Serial.println("ReadMessage: Parity error at Master Address!");
  348.     return(0);
  349.   }
  350.  
  351.   //Slave Address
  352.   sAddr = ReadBits(12);
  353.   if (ParityBit!=ReadBits(1)) {
  354.     Serial.println("ReadMessage: Parity error at Slave Address!");
  355.     return(0);
  356.   }
  357.   ReadBits(1);
  358.  
  359.   //control bits
  360.   cBits = ReadBits(4);
  361.   if (ParityBit!=ReadBits(1)) {
  362.     Serial.println("ReadMessage: Parity error at Control Bits!");
  363.     return(0);
  364.   }
  365.   ReadBits(1);
  366.  
  367.   //payload length
  368.   dlnth = ReadBits(8);
  369.   if (ParityBit!=ReadBits(1)) {
  370.     Serial.println("ReadMessage: Parity error at Payload Length!");
  371.     return(0);
  372.   }
  373.   ReadBits(1);
  374.  
  375.   //data loop
  376.   byte ii = dlnth;
  377.   while (ii-->0) {
  378.     data[ii]=ReadBits(8);
  379.     if (ParityBit!=ReadBits(1)){
  380.       Serial.println("ReadMessage: Parity error at Data "+String(ii)+"!");
  381.       return(0);
  382.     }
  383.     ReadBits(1);
  384.   }
  385.  
  386.  
  387.   LedOff();
  388.   return 1;
  389. }
  390.  
  391.  
  392.  
  393. //============================================================================================================================================================================================================
  394. //        Readbits()
  395. //        Takes a byte as input for the number of bits to read. Returns a word for the data recorded.
  396. //        This is used many times for each incoming message we read.
  397. //        Also sets the global variable ParityBit to whatever the expected parity value for these bits is.
  398. //============================================================================================================================================================================================================
  399.  
  400. word ReadBits(byte nbits) {
  401.   word data = 0;                                          //this will be the word we record and return
  402.   ParityBit=0;                                            //parity tracking
  403.   while (nbits-->0) {                                     //for each bit we must capture:
  404.     data<<=1;                                             //shift data left 1 bit
  405.     while(INPUT_IS_CLEAR) wdt_reset();                    //wait for a pulse
  406.     TCNT1=0;                                              //measure pulse
  407.     while(INPUT_IS_SET);                                  //wait for the end of the pulse
  408.     if (TCNT1<ZERO_LENGTH-(ZERO_LENGTH-ONE_LENGTH)/2) {   //if that was less than the half way mark between zero and one,
  409.       data |= 1;                                          //tack on a one
  410.       ParityBit = !ParityBit;                             //adjust parity
  411.     }
  412.   }
  413.   return data;
  414. }
  415.  
  416. //============================================================================================================================================================================================================
  417. //        DumpMessage()
  418. //        Dumps the contents of the last message read.
  419. //        This only happens when we encounter a message we aren't familiar with.
  420. //============================================================================================================================================================================================================
  421. void DumpMessage() {
  422.     //Serial.println("==============================================");
  423.     Serial.print("Master address: ");
  424.     Serial.print("0x"); Serial.println(mAddr,HEX);
  425.     Serial.print("Slave address: ");
  426.     Serial.print("0x"); Serial.println(sAddr,HEX);
  427.     Serial.print("Control bits: ");
  428.     Serial.print("B"); Serial.println(cBits,BIN);
  429.     Serial.print("Data length: ");
  430.     Serial.println(dlnth);
  431.     for (byte ii=0; ii<dlnth; ii++){
  432.       Serial.print("0x"); if (data[ii]<16) Serial.print("0");
  433.       Serial.print(data[ii],HEX);
  434.       Serial.print(", ");
  435.     }
  436.     Serial.println();
  437.     Serial.println("==============================================");
  438. }
  439. //============================================================================================================================================================================================================
  440. //        IdentifyMessage()
  441. //        Determines the type of message we have captured.
  442. //        Returns MessageID for the purpose of taking the action that message calls for.
  443. //        
  444. //============================================================================================================================================================================================================
  445. byte IdentifyMessage() {
  446.   bool match = false;
  447.   byte i;
  448.   for (i=0; i<MessageTableSize; i++) {
  449.    
  450.     //compare data sizes
  451.     //if size matches, begin comparing data
  452.     if ((pgm_read_byte_near(&MessageTable[i].PayloadLength)==dlnth) and (pgm_read_word_near(&MessageTable[i].MasterAddr)==mAddr) and (pgm_read_word_near(&MessageTable[i].SlaveAddr)==sAddr)) {
  453.       match = true;
  454.       for (byte ii=0; ii<dlnth; ii++) {
  455.         //if comparison data in place ii is variable,
  456.       if (pgm_read_word_near(&MessageTable[i].Payload[ii])>0xFF) {    
  457.           continue;
  458.       }
  459.         //compare data in place ii
  460.         //if data doesn't match, set match to false
  461.         if (pgm_read_word_near(&MessageTable[i].Payload[ii]) != data[ii]) {
  462.           match = false;
  463.           break;
  464.         }
  465.       }
  466.     }
  467.   //if match is still set to true after comparing all data, return the place in the table to which our message belongs
  468.   if (match) return(i);
  469.   }
  470.   Serial.println("===============Unknown=Message================");
  471.   DumpMessage();
  472.   return(i);
  473. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement