Identifying a rolling code IC

Hello everyone.

I'm having trouble identifying an IC.

I developed a project to test and identify encoders of RF433 remote controls commonly used to open garage doors.

I identified two main types of ICs.

The fixed code encoder HT6P20, no longer recommended due to its ease of being hacked,
and the rolling code encoder HCSxxx. Rolling code - Wikipedia

HT6P20 Datasheet https://pdf.datasheetcatalog.com/datasheets/120/170613_DS.pdf

HCS201 Datasheet https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/41098D.pdf

The project worked very well, I can read the serial numbers of both models and also the encrypted code of the rolling code IC.

I tested it with several controllers and they worked very well.

But I found a controller that did not work with my project, but works correctly with the gate module.

Analyzing the PCB of this controller I identified that it uses an IC with a different pinout.

I did extensive research looking for different types of remote control ICs, I searched with the numbers found on the IC of this control and with numbers found on the PCB of this control, but I couldn't find any datasheet.

It has diferent pinout.

Using a logic analyzer, I got the timing chart of the HCS201 IC and this IC.

Comparing the timing charts, I noticed small differences in timing both in the synchronization block and in the data bits.

With a small modification in the reading times of my project, I was able to read the data from this IC.

But I couldn't find the datasheet of the IC used.

Below are photos of the control, the schematic I created of this control, and the schematic of the project project I built, the timing charts of both ICs (HCS201 and the "VR2A1709" IC).

Although it is unnecessary, I will also post the code I used for this project. It was developed from two codes.

The HT6P20 part was extracted from the RCSwitch.h library example and the HSCxxx part was extracted from the link: Decode Rolling Code 433Mhz Signals with Arduino – Manuel Schütze

I would like to thank you in advance for any help in identifying this IC.

image

VR2A1709

HCS201

// HCS301 decoder //  https://www.manuelschutze.com/?p=333
// Modifiquei no tempo da linha 154 para ler controles do Antilhas

#include <LiquidCrystal_I2C.h>                                        // Biblioteca LCD I2C
LiquidCrystal_I2C lcd(0x27,  2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Endereco LCD I2C e pinos  Da caixinha
//#include "HT6.h"
bool flagHT6 = true;
#define selectCode  6
unsigned long LED_time = 0;

#define HCS_RECIEVER_PIN  3     //connected to 433Mhz receiver
#define LED  8                 //Led pin
class HCS201 {
  public:
    unsigned BatteryLow : 1;
    unsigned Repeat : 1;
    unsigned Btn1 : 1;
    unsigned Btn2 : 1;
    unsigned Btn3 : 1;
    unsigned Btn4 : 1;
    unsigned long SerialNum;
    unsigned long Encript;
    void print();
};

volatile boolean  HCS_Listening = true;
byte              HCS_preamble_count = 0;
uint32_t          HCS_last_change = 0;
uint32_t          HCS_start_preamble = 0;
uint8_t           HCS_bit_counter;
uint8_t           HCS_bit_array[66];
uint32_t          HCS_Te = 400;                //Typical Te duration
uint32_t          HCS_Te2_3 = 600;             //HCS_TE * 3 / 2
boolean           relayOn = false;
unsigned long     millisStart = 0;
unsigned long     relayDuration = 5 * 60 * 1000; //Duration of relay on

HCS201 hcs201;
//-----------------------------------------------------------------
void setup() {
  Serial.begin(115200);
  pinMode(selectCode, INPUT_PULLUP);
  pinMode(HCS_RECIEVER_PIN, INPUT);
  pinMode(LED, OUTPUT);
  LED_time = millis();
  attachInterrupt(1, HCS_interrupt, CHANGE);
  //Serial.println("Setup OK");
  lcd.begin(16, 2);                         // Inicialisa o LCD 16 x 2
  if (digitalRead(selectCode) == LOW) {
    flagHT6 = true;
    lcd.print("HT6 ");                       // print
    setup_HT6();
  }
  else {
    flagHT6 = false;
    lcd.print("FOB ");                       // print
    //setup_FOB();
  }
}
int myCount = 0;
//-----------------------------------------------------------------
void loop() {
  if (flagHT6 == true) {
    loopHT6();
  }
  else {
    long CurTime = millis();
    if (HCS_Listening == false) {
      HCS201 msg;                           //get message
      memcpy(&msg, &hcs201, sizeof(HCS201));
      msg.print();                          //do something
      HCS_Listening = true;
    }
  }
  if (millis() - LED_time >= 100) {
    digitalWrite(LED, LOW);
  }
  else {
    digitalWrite(LED, HIGH);
  }
  if (myCount > 1) {
    LED_time = millis();
    Serial.println(myCount);
    myCount = 0;
  }
}
//-----------------------------------------------------------------
void HCS201::print() {        //print data from hcs201
  String btn;
  if (Btn1 == 1) btn += "1";
  if (Btn2 == 1) btn += "2";
  if (Btn3 == 1) btn += "3";
  if (Btn4 == 1) btn += "4";
  String it2;
  it2 += "Encript=";
  it2 += Encript;
  it2 += " Serial=";
  it2 += SerialNum;
  it2 += " Button=";
  it2 += btn;
  it2 += " BatteryLow=";
  it2 += BatteryLow;
  it2 += " Rep=";
  it2 += Repeat;
  //Serial.println(it2);
  //Serial.println(SerialNum, HEX);
  if ( SerialNum != 0xFFFFFFF) {
    lcd.setCursor(0, 0);                            // Posição   linha
    lcd.print("SN ");                           // print
    lcd.print(SerialNum, HEX);
    lcd.print(" bt ");
    lcd.print(btn);
    lcd.print("   ");
    lcd.setCursor(0, 1);                            // Posição   linha
    lcd.print("Cd ");                           // print
    lcd.print(Encript, HEX);
    lcd.print("       ");
  }
}

//-----------------------------------------------------------------
void HCS_interrupt() {                //new data
  if (HCS_Listening == false) {
    return;
  }
  uint32_t cur_timestamp = micros();
  uint8_t  cur_status = digitalRead(HCS_RECIEVER_PIN);
  uint32_t pulse_duration = cur_timestamp - HCS_last_change;
  HCS_last_change = cur_timestamp;
  myCount = HCS_preamble_count;
  if (HCS_preamble_count < 12) {        // gets preamble
    if (cur_status == HIGH) {
      if ( ((pulse_duration > 150) && (pulse_duration < 500)) || HCS_preamble_count == 0) {
        if (HCS_preamble_count == 0) {
          HCS_start_preamble = cur_timestamp;
        }
      }
      else {
        HCS_preamble_count = 0;
        goto exit;
      }
    }
    else {
      if ((pulse_duration > 300) && (pulse_duration < 600)) {
        HCS_preamble_count ++;
        if (HCS_preamble_count == 12) {
          HCS_Te = (cur_timestamp - HCS_start_preamble) / 23;
          HCS_Te2_3 = HCS_Te * 3 / 2;
          HCS_bit_counter = 0;
          goto exit;
        }
      }
      else {
        HCS_preamble_count = 0;
        goto exit;
      }
    }
  }
  if (HCS_preamble_count == 12) {         // gets data
    LED_time = millis();
    if (cur_status == HIGH) {
      //if (((pulse_duration > 250) && (pulse_duration < 900)) || HCS_bit_counter == 0) {
      if (((pulse_duration > 250) && (pulse_duration < 1100)) || HCS_bit_counter == 0) {
        // beginning of data pulse
      }
      else {
        HCS_preamble_count = 0;    // incorrect pause between pulses
        goto exit;
      }
    }
    else {
      // end of data pulse
      if ((pulse_duration > 250) && (pulse_duration < 900)) {
        HCS_bit_array[65 - HCS_bit_counter] = (pulse_duration > HCS_Te2_3) ? 0 : 1;
        HCS_bit_counter++;
        if (HCS_bit_counter == 66) {  // all bits captured
          HCS_Listening = false;
          HCS_preamble_count = 0;
          hcs201.Repeat = HCS_bit_array[0];
          hcs201.BatteryLow = HCS_bit_array[1];
          hcs201.Btn1 = HCS_bit_array[2];
          hcs201.Btn2 = HCS_bit_array[3];
          hcs201.Btn3 = HCS_bit_array[4];
          hcs201.Btn4 = HCS_bit_array[5];
          hcs201.SerialNum = 0;
          for (int i = 6; i < 34; i++) {
            hcs201.SerialNum = (hcs201.SerialNum << 1) + HCS_bit_array[i];
          };
          uint32_t Encript = 0;
          for (int i = 34; i < 66; i++) {
            Encript = (Encript << 1) + HCS_bit_array[i];
          };
          hcs201.Encript = Encript;
        }
      }
      else {
        HCS_preamble_count = 0;
        goto exit;
      }
    }
  }
exit:;
}
// HT6
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
unsigned long myCode = 0xFFFFFFFF;
unsigned long myTime = 0xFFFFFFFF;
byte D1;
byte D2;
int ultimo = 3;
//--------------------------------------------------------------
void setup_HT6() {
  mySwitch.enableReceive(1);                // Receiver on interrupt 1 => that is pin #3
  mySwitch.setPulseLength(360);             // Largur do pulso
  mySwitch.setProtocol(6);                  // Protocolo usado
  mySwitch.setRepeatTransmit(5);            // repeticao de transmisao
}
//---------------------------------------------------------------------------------
void useDisplay(unsigned long code) {
  D1 = bitRead(code, 4);
  D2 = bitRead(code, 5);
  lcd.setCursor(0, 0);                            // Posição   linha
  lcd.print(code, HEX);                           // print
  lcd.print("    ");                              // print
  lcd.setCursor(9, 0);                            // Posição   linha
  lcd.print(code >> 6, HEX);                      // print
  lcd.print("    ");                              // print
  lcd.setCursor(0, 1);                            // Posição   linha
  lcd.print(D1, BIN);                             // print
  lcd.print(" ");                                 // print
  lcd.print(D2, BIN);                             // print
  lcd.print("   ");                               // print
  lcd.print(mySwitch.getReceivedBitlength());     // print
  lcd.print(" ");                                 // print
  lcd.print( mySwitch.getReceivedProtocol());     // print
  lcd.print("       ");                           // print
  lcd.setCursor(13, 1);                           // Posição   linha
  lcd.print((ultimo - 3) / 4);                    // print
}
//--------------------------------------------------------------
void loopHT6() {
  if (mySwitch.available()) {
    myCode =  mySwitch.getReceivedValue();
    //Serial.print(myCode); Serial.print(" / ");
    myTime = mySwitch.getReceivedDelay();
    //Serial.print(myTime); Serial.print(" / ");
    LED_time = millis();
    if (myTime > 350)   {
      /*   Serial.print("Received PPA Type ");
         Serial.print(myCode >> 6, HEX);
         Serial.print(" / ");
         Serial.print(bitRead(myCode, 4));
         Serial.print(" / ");
         Serial.print(bitRead(myCode, 5));
         Serial.print(" / ");
         Serial.print( mySwitch.getReceivedBitlength() );
         Serial.print("bit ");
         Serial.print("Protocol: ");
         Serial.println( mySwitch.getReceivedProtocol() );
      */
      useDisplay(myCode);
    }
    if (myTime < 350 and myTime > 200)   {
      /*
        Serial.print("Received other Type ");
        Serial.print(myCode >> 6, HEX);
        Serial.print(" / ");
        Serial.print(bitRead(myCode, 4));
        Serial.print(" / ");
        Serial.print(bitRead(myCode, 5));
        Serial.print(" / ");
        Serial.print( mySwitch.getReceivedBitlength() );
        Serial.print("bit ");
        Serial.print("Protocol: ");
        Serial.println( mySwitch.getReceivedProtocol() );
      */
      useDisplay(myCode);
    }
    mySwitch.resetAvailable();
  }
}

The logo on the chip seems to indicate Microchip. Maybe an 8 pin microcontroller like the PIC12 series or an ATtiny.

1 Like

Wow, how did I not think of that.
Good tip. I'll look for it based on the pinout.

I think it's PIC12xxx, because the ATtiny's power pins are different.

PIC12xxxx
Wide operating voltage range - 2.0V to 5.5V
image

image

Remember, there is NO feedback between the devices, so neither knows when a remote button is pressed multiple times. To cover that the receiving device generates 5 or more codes for future use. The next time it receives a code it must be one of the 5 codes. Perhaps more that 5 future codes are generated and saved. Such devices never have just one code that works.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.