⬆️ ⬇️

Copy dallas keys. Record on rw1990 (rw1990.1)

Hello! Today I want to talk about how to make a device that allows you to copy Touch Memory company Dallas. The article is intended for those who have experience in programming in C / C ++ languages. I don’t intend to tell how the OneWire protocol works. On the Internet, a lot of information on this topic.



So, what we need for the manufacture of this device:



1) Atmega8

2) FTDI RL232 converts USB to USART

3) Driver for FTDI RL232

4) Programmer (I used USBasp)

5) Visual Studio

6) Atmel Studio

7) Breadboard



With this set you can move on. To get started, prepare a board on which to place the components.

I did it like this:

')

image



image



image



image



Now let's define the parameters of USART atmega8. I have these:

1) Stop bit - 1

2) 9600boud

3) Parity bit - no



I will use the internal 4Mhz generator, so I will tune the UBRR register for this frequency. Here is the piece of code where the USART setup is going:



DDRD|=(1<<1); DDRD&=~(1<<0); UBRRH=0; UBRRL=25; UCSRB|=(1<<RXEN)|(1<<TXEN); UCSRC|=(1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); 


It's time to disassemble the record protocol for rw1990 discs. The command to read the 8-byte code is identical with the dallas keys.



Writing to rw1990 happens like this:

1) Send a reset pulse, and expect the presence of a pulse;

2) Send the command 0xD1, thereby allowing the recording;

3) Time slot, send a logical "0" (see Figure 1);

4) Send a reset pulse and wait for the presence of a pulse;

5) Send the write command, 0xD5;

6) We send an 8-byte code (all bits are inverted), the transfer is different from the oneWire protocol (see Figure 1);

7) Send a reset pulse and wait for the presence of a pulse;

8) Send the command 0xD1, thereby prohibiting the recording;

9) Time slot, send a logical "1" (see Figure 1).



Figure 1:



image



A piece of code where the recording occurs:



 bool onewire_init(){ onewire_low(); _delay_us(480); onewire_high(); _delay_us(2); for(uint8_t i= 60;i;i++){ if(!onewire_level()){ while(!onewire_level()); return true; } _delay_us(1); } return false; } void time_slot(uint8_t data){ onewire_low(); if(data) _delay_us(6); else _delay_us(60); onewire_high(); _delay_ms(10); } void rw1990_write_bit(uint8_t data){ onewire_low(); if (data) _delay_us(6); else _delay_us(60); onewire_high(); _delay_ms(2); } void rw1990_write(uint8_t data){ for(uint8_t i=0;i<8;i++){ rw1990_write_bit(data & 0x01); data>>=1; } } bool rw1990_newcode(uint8_t* buf){ if (onewire_init()){ onewire_send(0xD1); time_slot(0); }else return false; if(onewire_init()){ onewire_send(0xD5); for(uint8_t i=0;i<8;i++){ rw1990_write(~buf[i]); } }else return false; if (onewire_init()){ onewire_send(0xD1); time_slot(1); }else return false; return true; } 


I hope it is clear. We still need to write an application that will communicate with the microcontroller. That is, we will send requests to read and write the key to the microcontroller from the computer. I will lay out all source codes under a topic. The application is quite simple.



However, the video shows everything.



Source code for atmega8
 #define F_CPU 4000000 #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #define ONEWIRE_PORT PORTB #define ONEWIRE_DDR DDRB #define ONEWIRE_PIN PINB #define ONEWIRE_PIN_NUM 0 void usart_init(); void onewire_high(); void onewire_low(); uint8_t onewire_level(); bool onewire_init(); void onewire_write_bit(uint8_t); void onewire_send(uint8_t); uint8_t onewire_read_bit(); uint8_t onewire_read(); bool onewire_readrom(uint8_t*); void time_slot(uint8_t); void rw1990_write_bit(uint8_t); void rw1990_write(uint8_t); bool rw1990_newcode(uint8_t*); uint8_t usart_read(); uint8_t rom[8]; uint8_t new_rom[8]; uint8_t t=0; ISR (USART_UDRE_vect){ UDR=t; UCSRB &=~(1<<UDRIE); t=0; } int main(void) { usart_init(); asm("sei"); while(1) { uint8_t r=usart_read(); if (r==0x40){ for(uint8_t i=0;i<8;i++){ new_rom[i]=usart_read(); } if(rw1990_newcode(new_rom)){ t=0x45; UCSRB |=(1<<UDRIE); }else{ t=0x46; UCSRB |=(1<<UDRIE); } }else if(r==0x30){ if(onewire_readrom(rom)){ t=0x35; UCSRB |= (1<<UDRIE); for (uint8_t i=0;i<8;i++){ t=rom[i]; UCSRB |= (1<<UDRIE); _delay_ms(1); } }else{ t=0x36; UCSRB |= (1<<UDRIE); } } } } void onewire_high(){ ONEWIRE_PORT &=~ (1<<ONEWIRE_PIN_NUM); ONEWIRE_DDR &=~ (1<<ONEWIRE_PIN_NUM); } void onewire_low(){ ONEWIRE_PORT &=~ (1<<ONEWIRE_PIN_NUM); ONEWIRE_DDR |= (1<<ONEWIRE_PIN_NUM); } uint8_t onewire_level(){ return ONEWIRE_PIN & (1<<ONEWIRE_PIN_NUM); } bool onewire_init(){ onewire_low(); _delay_us(480); onewire_high(); _delay_us(2); for(uint8_t i= 60;i;i++){ if(!onewire_level()){ while(!onewire_level()); return true; } _delay_us(1); } return false; } void onewire_write_bit(uint8_t bit){ onewire_low(); if(bit){ _delay_us(5); onewire_high(); _delay_us(90); }else{ _delay_us(90); onewire_high(); _delay_us(5); } } void onewire_send(uint8_t data){ for(uint8_t i=0;i<8;i++){ onewire_write_bit(data&0x01); data>>= 1; } } void usart_init(){ DDRD|=(1<<1); DDRD&=~(1<<0); UBRRH=0; UBRRL=25; UCSRB|=(1<<RXEN)|(1<<TXEN); UCSRC|=(1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); } uint8_t onewire_read_bit(){ onewire_low(); _delay_us(2); onewire_high(); _delay_us(8); uint8_t r = onewire_level(); _delay_us(80); return r; } uint8_t onewire_read(){ uint8_t r = 0; for (uint8_t p = 8; p; p--) { r >>= 1; if (onewire_read_bit()) r |= 0x80; } return r; } void time_slot(uint8_t data){ onewire_low(); if(data) _delay_us(6); else _delay_us(60); onewire_high(); _delay_ms(10); } void rw1990_write_bit(uint8_t data){ onewire_low(); if (data) _delay_us(6); else _delay_us(60); onewire_high(); _delay_ms(2); } void rw1990_write(uint8_t data){ for(uint8_t i=0;i<8;i++){ rw1990_write_bit(data & 0x01); data>>=1; } } bool rw1990_newcode(uint8_t* buf){ if (onewire_init()){ onewire_send(0xD1); time_slot(0); }else return false; if(onewire_init()){ onewire_send(0xD5); for(uint8_t i=0;i<8;i++){ rw1990_write(~buf[i]); } }else return false; if (onewire_init()){ onewire_send(0xD1); time_slot(1); }else return false; return true; } bool onewire_readrom(uint8_t* buf){ if (onewire_init()){ onewire_send(0x33); for(uint8_t i=0;i<8;i++){ buf[i]=onewire_read(); } }else return false; return true; } uint8_t usart_read(){ while(!(UCSRA & (1 << RXC))); return UDR; } 




Of course, it was possible to do everything in OOP style, but for some reason I decided so.



The source of the so-called iButton terminal
main.cpp
 #include <Windows.h> #include <iostream> #include "ComPort.h" using namespace std; int main(){ char buf_file[10]; wchar_t file[10]; char name[20]; char command[10]; unsigned char rom[8]; cout<<"Enter COM port: "; cin>>buf_file; cout<<"Enter your name: "; cin>>name; mbstowcs(file,buf_file,10); ComPort port((LPCWSTR)file,CBR_9600); cout<<"Welcome "<<name<<"! "<<"If you need help, you can write command \"help\"."<<endl; while(strcmp(command,"exit")){ cout<<name<<"> "; cin>>command; if(!strcmp(command,"write_rom")){ scanf("%x %x %x %x %x %x %x %x",&rom[0],&rom[1],&rom[2],&rom[3],&rom[4],&rom[5],&rom[6],&rom[7]); for(int i=0;i<50;i++){ port.ComWrite(0x40); port.ComWrite((char*)rom,sizeof(rom)); char recv=port.ComRead(); if(recv==0x45){ cout<<"Device> write successfull!"<<endl; break; }else if(recv==0x46){ cout<<"Device> write fail!"<<endl; } Sleep(100); } }else if(!strcmp(command,"read_rom")){ for(int i=0;i<50;i++){ port.ComWrite(0x30); char recv=port.ComRead(); if(recv==0x35){ for(int i=0;i<8;i++){ rom[i]=port.ComRead(); } cout<<"Device> read successfull! "; printf("%02X %02X %02X %02X %02X %02X %02X %0X\n",rom[0],rom[1],rom[2],rom[3],rom[4],rom[5],rom[6],rom[7]); break; }else if(recv==0x36){ cout<<"Device> read fail!"<<endl; } Sleep(100); } } } } 




ComPort.cpp
 #include <Windows.h> #include "ComPort.h" ComPort::ComPort(LPCWSTR str,DWORD baud) { hSerial=CreateFile(str,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); ComPort::baud=baud; SerialParams.DCBlength=sizeof(SerialParams); if(!GetCommState(hSerial,&SerialParams)) MessageBox(NULL,L"Getting state error!",L"Error!",MB_OK|MB_ICONERROR); SerialParams.BaudRate=baud; SerialParams.ByteSize=8; SerialParams.StopBits=ONESTOPBIT; SerialParams.Parity=NOPARITY; if(!SetCommState(hSerial,&SerialParams)) MessageBox(NULL,L"Error setting serial port state!",L"Error!",MB_OK|MB_ICONERROR); } void ComPort::ComWrite(unsigned char buf) { DWORD send; WriteFile(hSerial,&buf,1,&send,NULL); } void ComPort::ComWrite(char* buf,int size) { DWORD send; WriteFile(hSerial,buf,size,&send,NULL); } bool ComPort::ComRead(char* buf,int size) { DWORD recv; char recvchar; ZeroMemory(buf,size); for(int i=0;i<size;i++){ ReadFile(hSerial,&recvchar,1,&recv,0); if(recvchar=='~') break; buf[i]=recvchar; } return true; } char ComPort::ComRead() { DWORD recv; char recvchar; ReadFile(hSerial,&recvchar,1,&recv,0); return recvchar; } ComPort::~ComPort(void) { CloseHandle(hSerial); } 




ComPort.h
 class ComPort { private: HANDLE hSerial; DCB SerialParams; LPCWSTR sPort; int baud; public: ComPort(LPCWSTR,DWORD); void ComWrite(unsigned char); void ComWrite(char*,int); bool ComRead(char*,int); char ComRead(); ~ComPort(void); }; 








The code, of course, is not the best, because I tried to write faster, but it still works great.



This is what I got at the end:



image



image



image



image



And here is the video:



Source: https://habr.com/ru/post/260891/



All Articles