forked from Elektron2016/key_copy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
kt-01.c
138 lines (119 loc) · 2.23 KB
/
kt-01.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
* kt_01.c
*
* Created: 28.01.2016 0:09:48
* Author: Elektron
*/
#include <avr/io.h>
#include <util/delay.h>
#include "kt-01.h"
void kt_init()
{
KT_PORT &= ~(1<<KT_LINE);
KT_DDR &= ~(1<<KT_LINE);
KT_PORT &= ~(1<<KT_PROG);
KT_DDR |= 1<<KT_PROG;
}
uint8_t kt_crc(uint8_t* data, uint8_t len)
{
uint8_t crc = 0;
while (len--)
{
crc ^= *data++;
for (uint8_t i=0; i<8; i++){
if (crc & 0x01)
crc = (crc >> 1) ^ 0x0B;
else
crc >>= 1;
}
}
return crc;
}
uint8_t kt_crc_check(uint8_t* data)
{
uint8_t zero = 0;
uint8_t crc = kt_crc(data,16);
for (uint8_t i=0;i<16;i++) if(data[i]!=0) zero++;
for (uint8_t i=0;i<8;i++)
if(data[i] != data[i+8]) return 1;
if(zero==0) return 1;
if(crc==0)return 0;
return 1;
}
void kt_out(uint8_t databyte)
{
if (databyte == 0){
KT_DDR |= (1<<KT_LINE);
}else{
KT_DDR &= ~(1<<KT_LINE);
}
}
uint8_t kt_in(void)
{
return KT_PIN & (1<<KT_LINE);
}
void kt_write_byte(uint8_t data)
{
for (uint8_t i=0;i<8;i++){
if (data & 0x01){
kt_out(0);
_delay_us(5);
kt_out(1);
}else{
kt_out(0);
_delay_us(90);
kt_out(1);
}
_delay_ms(13);
data >>= 1;
}
}
uint8_t kt_read_byte(void)
{
uint8_t bit,result = 0;
for (uint8_t i=0;i<8;i++){
kt_out(0);
_delay_us(10);
kt_out(1);
_delay_us(25);
bit = kt_in();
_delay_us(175);
result >>= 1;
if(bit) result |= 0x80;
}
return result;
}
uint8_t kt_reset(void)
{
kt_out(0);
_delay_ms(1);
kt_out(1);
_delay_us(80);
if(kt_in() == 0) return 1;
for(uint8_t i=0;;i++){
if(kt_in() == 0) break;
if(i > 20) return 2;
_delay_us(10);
}
_delay_us(240);
return 0;
}
uint8_t kt_read_rom(uint8_t* data)
{
if(kt_reset()) return KT_NO_KEY;
for(uint8_t i=0;i<16;i++) data[i] = kt_read_byte();
if(kt_crc_check(data)) return KT_CRC_ERR;
return KT_READ_ROM_OK;
}
uint8_t kt_write_rom(uint8_t* data)
{
if(kt_reset()) return KT_NO_KEY;
KT_PORT |= 1<<KT_PROG;
_delay_ms(45);
for(uint8_t i=0;i<16;i++) kt_write_byte(data[i]);
KT_PORT &= ~(1<<KT_PROG);
if(kt_reset()) return KT_NO_KEY;
for(uint8_t i=0;i<16;i++)
if(kt_read_byte() != data[i]) return KT_CRC_ERR;
return KT_READ_ROM_OK;
}