Друзья, помогите разобраться что за интерфейс передачи данных Starline

Отчитываюсь, допилил! Надеюсь кому-то , кроме меня, это будет полезно. Скетч:

#include <EEPROM.h>
#define RX 3  // пин ардуино, к которому подключать линию RX GSM (не менять!)
#define TX 2  // пин ардуино, к которому подключать линию TX GSM

#define DEBUG // раскомментировать, если нужна отладка в терминал. Закомментировать эту строку, когда вставляете эту городьбу в свой проект)

volatile byte dataRX[10] = {0}; // буфер приема данных от сигналки
enum statesRX {WAIT_FALL, WAITSTROB, CLOCKING_DETECTED};    // возможные состояния приемника
volatile byte stateRX = WAIT_FALL ;  // переменная состояния приемника
volatile byte bitNumberRX  = 0 ; 
volatile byte byteNumberRX = 0 ;  
volatile bool SLmessage_received  = 0;   // флаг что принято новое сообщение от сигналки

volatile byte dataTX[10]= {0}; // буфер передачи данных на сигналку (пакет байт команды)
enum statesTX {WAIT_CLOCKING, PROPUSK, TXbyCLOCK, TXtoIDLE}; //возможные состояния передатчика 
volatile byte stateTX = WAIT_CLOCKING ;   // переменная состояния передатчика
volatile byte bitNumberTX  = 0 ; 
volatile byte byteNumberTX = 0 ;  

byte SL_key[2]={0}; // байты ключа сигнализации

// таймеры возврата в bus-Idle в случае неответов от сигналки
bool Timer_waitCLOCKING_from_Starline    = 0; 
uint32_t prev_waitCLOCKING_from_Starline = 0;
enum protectTimer_states {TIMER_OFF, TIMER_WAIT_RESPONSE, TIMER_PROTECT, TIMER_LASTSTATE};
byte Timer_waitRESPONSE_from_Starline    = 0; 
uint32_t prev_waitRESPONSE_from_Starline = 0;

byte Timer_needRepeat          = 0; 
uint32_t prev_timer_needRepeat = 0;
bool needPropusk = 0 ;
byte RepeatCommand = 0 ; 
byte CountRepeat = 0 ; 

#define CLOCK_ON  TCCR2B=2
#define CLOCK_OFF TCCR2B=0
#define SEND_CLOCKING_AND_READ_BITS    ISR(TIMER2_COMPA_vect)  

const uint8_t ZAPROS     = 0x42;
const uint8_t START_ENG  = 0x21;
const uint8_t STOP_ENG   = 0x20;
const uint8_t OHRANA_ON  = 0x11;
const uint8_t OHRANA_OFF = 0x10;

bool Doors    = 0 ; 
bool Locks    = 0 ;
bool Ohrana   = 0 ;
bool Trunk    = 0 ; 
bool Hood     = 0 ; 
bool Ignition = 0 ; 
bool Brake    = 0 ; 
bool Engine   = 0 ; 
bool Trevoga  = 0 ; 
bool Tiltsensor   = 0 ; 
bool Shocksensor  = 0 ; 

 

void setup() {

   pinMode (TX, OUTPUT);       // линию TX на выход 
   digitalWrite (TX, 1);       // и ставим в busIdle
   pinMode (RX, INPUT_PULLUP); // линию RX на вход с подтяжкой

#ifdef DEBUG
Serial.begin(115200); Serial.println(); Serial.println(F("Arduino Restart"));
Serial.print(F("Starline Key:  "));
#endif

for (byte i=0; i<2; i++)
{
    SL_key[i] = EEPROM.read(i+200); 
   #ifdef DEBUG
    if (SL_key[i]<0xF){Serial.print("0");} Serial.print(SL_key[i], HEX); Serial.print(F(" "));
   #endif
}
 #ifdef DEBUG
 Serial.println();
 #endif
//---------настройка таймера2 для выполнения нами тактирования передачи от сигналки (обработчик выскочит раз в 100мкс).
TCCR2A = 2 ;
TCCR2B = 0;
OCR2A = 198; // установка регистра совпадения (100 мкс для прескалера 8) 
TIMSK2 = 2; // разрешить прерывание по таймеру2 по сравнению A 
//TCCR2B = 2; // включ таймер раз в 100мкс

}

void loop() 
{
 SL_Data(); // работа протокола SL_DATA
}

void SL_Data()
{
//таймеры сброса тактирования или сброса линии TX при передаче в случае неответов от оппонента
 timers_to_protect_against_failures();

 #ifdef DEBUG
 //иницирование отправки команд на сигналку через терминал
 Command_to_Starline_from_Terminal();
 #endif
 
 //обработка принятых сообщений от сигналки
 processing_of_received_SLmessages();
 
 //отправка сигнала тактирования на сигналку 
 send_CLOCKING_to_Starline();
}

void send_CLOCKING_to_Starline(){

if (Timer_waitRESPONSE_from_Starline!=TIMER_PROTECT){ // тактируем, если не включена защитная задержка глюков связи
  
bool curRX = digitalRead(RX); 
static bool lastRX = curRX;
 if (lastRX != curRX){ // если состояние линии RX изменилось
 if (stateTX==WAIT_CLOCKING && stateRX == WAIT_FALL) // если статус приемника и передатчика "ждем спад"
  {
  if (lastRX && !curRX){ // если увидели спад на RX, значит сигналка хочет передавать, ниже отправляем ей тактирвание
  stateRX = WAITSTROB;
  delayMicroseconds (100);
  if (bool((1 << 3) & PIND)) {stateRX = WAIT_FALL; return;} // если было ложное срабатывание RX пина, выходим. 
  //ниже включение таймера защиты от возможных глюков при неответах
  if (Timer_waitRESPONSE_from_Starline==TIMER_OFF) {Timer_waitRESPONSE_from_Starline = TIMER_WAIT_RESPONSE; prev_waitRESPONSE_from_Starline = millis();}
  digitalWrite (TX,0);   // короткий строб в ноль, делаем всё по снифферской осциллограмме с ори обмена данными
  delayMicroseconds (40); // длина строба
  CLOCK_ON; // включаем тактирование для оппонента. 
  }
  }
 lastRX = curRX;
 }
                                                  }
}

SEND_CLOCKING_AND_READ_BITS // обработчик вылазит раз в 100мкс, тактируем для сигналки и читаем очередной бит от неё
{
       if (stateRX == WAITSTROB) {stateRX = CLOCKING_DETECTED; PORTD ^= (1 << 2);} 
  else if (stateRX == CLOCKING_DETECTED) 
      {
      if (bool((1 << 3) & PIND)){dataRX[byteNumberRX]|= (1<<(bitNumberRX));}// читаем 
      else {dataRX[byteNumberRX]&=~(1<<(bitNumberRX));}                     // очередной бит 
      PORTD ^= (1 << 2); // тактируем, изменив состояние пина TX на противоположное 
      if (bitNumberRX==7 && byteNumberRX == 9) {endRX(); SLmessage_received = 1; return;} // сообщение полностью принято
      bitNumberRX++; if (bitNumberRX==8){bitNumberRX=0; byteNumberRX++;} // рост счётчиков бит и байт
       }
}
void endRX(){CLOCK_OFF; bitNumberRX=0; byteNumberRX=0; stateRX = WAIT_FALL;}

void processing_of_received_SLmessages()

{if (SLmessage_received){
  #ifdef DEBUG
    Serial.print ("Starline Response:    ");
  #endif 
    byte CS = 0 ;
    for (int i=0; i<10; i++) 
{
    if (i<9)CS+=dataRX[i]; // подсчёт CS
    #ifdef DEBUG
    if (dataRX[i]<=0xF)Serial.print("0"); Serial.print(dataRX[i], HEX); Serial.print(" "); 
    #endif
    if (i==9) 
     {
      #ifdef DEBUG
      Serial.print("    CS is "); 
      #endif 
            if (CS==dataRX[i]) // если получен валидный ответ от сигналки
            { 
              Timer_waitCLOCKING_from_Starline = 0;         // сбрасываем таймер ожидания тактирования от сигналки
              Timer_waitRESPONSE_from_Starline = TIMER_OFF; // сбрасываем таймер ожидания ответа от сигналки
              Timer_needRepeat = 0 ; CountRepeat = 0 ; 
              #ifdef DEBUG
              Serial.println("OK!   "); 
              #endif
              if (dataRX[0]==0x0B && dataRX[4]==0x00) // принята процедура привязки GSM, запоминаем ключ Starline
              {
                 Registration_SL_GSM();
                #ifdef DEBUG 
                Serial.println(F("Registration GSM successfully completed!")); 
                #endif
              }
else {              
Doors       = (bool((1 << 0) & dataRX[1]));
Trunk       = (bool((1 << 2) & dataRX[1]));
Hood        = (bool((1 << 3) & dataRX[1]));
Ignition    = (bool((1 << 3) & dataRX[3]));
Brake       = (bool((1 << 4) & dataRX[1]));
Locks       = (bool((1 << 5) & dataRX[1]));
Ohrana      = (bool((1 << 6) & dataRX[1]));
Trevoga     = (bool((1 << 4) & dataRX[2])); 
Shocksensor = (bool((1 << 1) & dataRX[5])); 
Tiltsensor  = (bool((1 << 0) & dataRX[6])); 
#ifdef DEBUG
 Serial.print (" Door: "); Serial.print (Doors);  Serial.print ("  Ign: "); Serial.print (Ignition);
 Serial.print ("  Brake: "); Serial.print (Brake); Serial.print ("  Trunk: "); Serial.print (Trunk);
 Serial.print ("  Hood: "); Serial.print (Hood); Serial.print ("  Locks: "); Serial.print (Locks);
 Serial.print ("  Ohrana: "); Serial.print (Ohrana); Serial.print ("  Trevoga: "); Serial.print (Trevoga);
 Serial.print ("  Shock: "); Serial.print (Shocksensor); Serial.print ("  Tilt: "); Serial.println (Tiltsensor);
#endif
}
              
            }
            else  // Если CS неправильная
              {
              #ifdef DEBUG
              Serial.println("Error!!!");
              #endif
              }  
      }
}
 
  SLmessage_received = 0 ; 
  #ifdef DEBUG
  Serial.println();
  #endif
 }
}

#ifdef DEBUG
void Command_to_Starline_from_Terminal() // инициирование отправки команд на сигналку с терминала
{
  if (Serial.available())
  { 
      Serial.println();
      byte inbyte = Serial.read();
       if (inbyte == 'z') {Serial.println (F(" Send SMS Zapros Sostoyanya: ")); Send_To_Starline (ZAPROS);}
  else if (inbyte == '1') {Serial.println (F(" Send SMS Ohrana ON: "));         Send_To_Starline (OHRANA_ON);}
  else if (inbyte == '0') {Serial.println (F(" Send SMS Ohrana OFF: "));        Send_To_Starline (OHRANA_OFF);}
  else if (inbyte == 'r') {Serial.println (F(" GSM is reset!  "));    Reset_SL_GSM(); }
  else if (inbyte == 'p') {needPropusk=!needPropusk;  Serial.print  (F("Propusk "));  Serial.println (needPropusk);}
  
  }
}
#endif

void Send_To_Starline(const byte &SLcommand)  // процедура отправки команды на сигналку
{
  if (stateRX > WAIT_FALL) {delay (200);} 
  RepeatCommand = SLcommand;
  dataTX[0]=0x0A;
  dataTX[1]=millis();
  dataTX[2]=(dataTX[1]^SLcommand)^SL_key[0];
  dataTX[3]=(dataTX[1]^SLcommand)^SL_key[1];
  dataTX[4]=0xFF;
  byte CS = 0 ;
  for (byte i=0; i<5;i++) {CS+=dataTX[i];}
  dataTX[9]=CS;
  #ifdef DEBUG
  Serial.print (" Send to Starline:  ");
  for (byte i=0; i<10;i++) {if (dataTX[i]<=0xF)Serial.print("0"); Serial.print(dataTX[i], HEX); Serial.print(" ");}
  Serial.println();
  #endif
  PORTD &=~(1 << 2);                     // садим в 0 линию передачи , инициируя желание передавать данные
  Timer_waitCLOCKING_from_Starline = 1; prev_waitCLOCKING_from_Starline = millis(); // включаем таймер защиты
  Timer_needRepeat = 1; prev_timer_needRepeat =  millis();
  attachInterrupt(1, Accept_clocking_and_transmit_bits, FALLING); // и ждем тактирования от сигналки (принимать тактирование будет внеш прерывание)
}


void Accept_clocking_and_transmit_bits () //обработчик внешнего прерывания, выступает как приёмник тактирования от сигналки для выполнения нашей ей передачки. 
{
 
 if (stateTX==WAIT_CLOCKING){if (needPropusk) stateTX=PROPUSK; else stateTX=TXbyCLOCK; attachInterrupt(1, Accept_clocking_and_transmit_bits, CHANGE);return;} 
//--------------ниже передача команды на шину по тактированию от сигналки-----------
 else if (needPropusk && stateTX==PROPUSK){stateTX=TXbyCLOCK;}
 else if (stateTX==TXbyCLOCK) // принимаем тактирование от сигналки и по нему отправляем побитно команду
 {
   if (bool((1 << (bitNumberTX)) & dataTX[byteNumberTX])) { PORTD |=(1 << 2); } // читаем очередной бит из команды 
   else {PORTD &=~(1 << 2); }                                                   // и выставляем его на пине TX 
//----------------------------------------------------------------------------------    
    if (byteNumberTX==9 && bitNumberTX == 7)  { endTX(); return;}// если все 80 бит переданы, выходим , сбросив переменные и откл внеш прерывание 
        bitNumberTX++; if (bitNumberTX == 8) {bitNumberTX = 0 ;byteNumberTX++;}
 }
}

void endTX() {detachInterrupt(1); stateTX=TXtoIDLE; bitNumberTX=0;  byteNumberTX=0;}

void timers_to_protect_against_failures()
{
  if (stateTX==TXtoIDLE){delayMicroseconds(100); digitalWrite(TX,1);stateTX=WAIT_CLOCKING;}
 
  if (Timer_waitCLOCKING_from_Starline && millis()- prev_waitCLOCKING_from_Starline>=200)
     {
      Timer_waitCLOCKING_from_Starline=0;
      endTX();
     }

   if (Timer_needRepeat && millis() - prev_timer_needRepeat>=3500) 
      {
        CountRepeat++; if  (CountRepeat>=3) CountRepeat = 3 ; 
        Timer_needRepeat = 0 ; 
        needPropusk=!needPropusk;
        if (CountRepeat<3){Send_To_Starline (RepeatCommand);}
      }

     
  if (Timer_waitRESPONSE_from_Starline>0 && millis() - prev_waitRESPONSE_from_Starline>=4000) 
     {
      
      Timer_waitRESPONSE_from_Starline++; 
       if (Timer_waitRESPONSE_from_Starline==TIMER_PROTECT) {endRX(); digitalWrite(TX,1);}
  else if (Timer_waitRESPONSE_from_Starline>=TIMER_LASTSTATE){Timer_waitRESPONSE_from_Starline = TIMER_OFF;}
      prev_waitRESPONSE_from_Starline = millis();
     }     
}

void Reset_SL_GSM () {SL_key[0]=0xFF; SL_key[1]=0xFF; EEPROM.write(200,0xFF);EEPROM.write(201,0xFF);}

void Registration_SL_GSM () {SL_key[0]=dataRX[1]; SL_key[1]=dataRX[2]; EEPROM.write(200,dataRX[1]);EEPROM.write(201,dataRX[2]);}




ну и пример лога:

Arduino Restart
Starline Key:  FF FF 

отправляю запрос состояния с терминала 
 Send SMS Zapros Sostoyanya: 
 Send to Starline:  0A 91 2C 2C FF 00 00 00 00 F2 
 Send to Starline:  0A 3F 82 82 FF 00 00 00 00 4C 
 Send to Starline:  0A EC 51 51 FF 00 00 00 00 97 

выше нет ответов от сигналки, т.к. GSM ещё не привязан .
Начинаю на сигналке процедуру привязки GSM (7 раз нажал кн валет и включил 
зажигание)

Starline Response:    0A 00 00 08 FF 00 00 00 00 11     CS is OK!   
 Door: 0  Ign: 1  Brake: 0  Trunk: 0  Hood: 0  Locks: 0  Ohrana: 0  Trevoga: 0  Shock: 0  Tilt: 0

Starline Response:    0B 58 61 00 00 00 00 00 00 C4     CS is OK!   
Registration GSM successfully completed!

Starline Response:    0A 80 00 08 FF 00 00 00 00 91     CS is OK!   
 Door: 0  Ign: 1  Brake: 0  Trunk: 0  Hood: 0  Locks: 0  Ohrana: 0  Trevoga: 0  Shock: 0  Tilt: 0

т.к. GSM успешно привязан , выключаю зажигание
Starline Response:    0A 80 00 00 FF 00 00 00 00 89     CS is OK!   
 Door: 0  Ign: 0  Brake: 0  Trunk: 0  Hood: 0  Locks: 0  Ohrana: 0  Trevoga: 0  Shock: 0  Tilt: 0

Starline Response:    0A 00 00 00 FF 00 00 00 00 09     CS is OK!   
 Door: 0  Ign: 0  Brake: 0  Trunk: 0  Hood: 0  Locks: 0  Ohrana: 0  Trevoga: 0  Shock: 0  Tilt: 0

Ставлю на охрану с терминала
 Send SMS Ohrana ON: 
 Send to Starline:  0A 9D D4 ED FF 00 00 00 00 67 


Starline Response:    0A 60 00 00 FF 00 00 00 00 69     CS is OK!   
 Door: 0  Ign: 0  Brake: 0  Trunk: 0  Hood: 0  Locks: 1  Ohrana: 1  Trevoga: 0  Shock: 0  Tilt: 0

Снимаю с охраны с терминала
 Send SMS Ohrana OFF: 
 Send to Starline:  0A EA A2 9B FF 00 00 00 00 30 


Starline Response:    0A 00 00 00 FF 00 00 00 00 09     CS is OK!   
 Door: 0  Ign: 0  Brake: 0  Trunk: 0  Hood: 0  Locks: 0  Ohrana: 0  Trevoga: 0  Shock: 0  Tilt: 0

тут я включил зажигание 
Starline Response:    0A 00 00 08 FF 00 00 00 00 11     CS is OK!   
 Door: 0  Ign: 1  Brake: 0  Trunk: 0  Hood: 0  Locks: 0  Ohrana: 0  Trevoga: 0  Shock: 0  Tilt: 0

Starline Response:    0A 80 00 08 FF 00 00 00 00 91     CS is OK!   
 Door: 0  Ign: 1  Brake: 0  Trunk: 0  Hood: 0  Locks: 0  Ohrana: 0  Trevoga: 0  Shock: 0  Tilt: 0

тут я выключил зажигание 
Starline Response:    0A 80 00 00 FF 00 00 00 00 89     CS is OK!   
 Door: 0  Ign: 0  Brake: 0  Trunk: 0  Hood: 0  Locks: 0  Ohrana: 0  Trevoga: 0  Shock: 0  Tilt: 0

Starline Response:    0A 00 00 00 FF 00 00 00 00 09     CS is OK!   
 Door: 0  Ign: 0  Brake: 0  Trunk: 0  Hood: 0  Locks: 0  Ohrana: 0  Trevoga: 0  Shock: 0  Tilt: 0

2 лайка