1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 | #include <avr/eeprom.h>
|
4 | #include <avr/power.h>
|
5 | #include <util/delay.h>
|
6 |
|
7 | #define WRITE_PERIOD 16
|
8 | #define EEPROM_ADDR 0b10100000
|
9 | #define EEPROM_SIZE 0x4000
|
10 |
|
11 | #define KB_CLOCK PB1
|
12 | #define KB_DATA PB0
|
13 | #define KB_SWITCH PB2
|
14 |
|
15 | #define cbi(reg, bit) reg &= ~(1<<bit)
|
16 | #define sbi(reg, bit) reg |= (1<<bit)
|
17 |
|
18 | //--i2c
|
19 | #define I2C_SCL PB3
|
20 | #define I2C_SDA PB4
|
21 |
|
22 | #define SCL_L sbi(DDRB, I2C_SCL)
|
23 | #define SCL_H cbi(DDRB, I2C_SCL)
|
24 |
|
25 | #define SDA_L sbi(DDRB, I2C_SDA)
|
26 | #define SDA_H cbi(DDRB, I2C_SDA)
|
27 | #define SDA_LINE PINB&(1<<I2C_SDA)
|
28 |
|
29 | //#define I2C_DELAY _delay_us(5);
|
30 | //#define I2C_DELAY asm ("nop");
|
31 | #define I2C_DELAY ;
|
32 | #define I2C_CLOCK I2C_DELAY; SCL_H; I2C_DELAY; SCL_L;
|
33 | #define I2C_START SDA_L; I2C_DELAY; SCL_L;
|
34 | #define I2C_STOP I2C_DELAY; SCL_H; I2C_DELAY; SDA_H;/* I2C_DELAY;*/
|
35 | //--
|
36 |
|
37 | //--kb
|
38 | #define CLOCK_L sbi(DDRB, KB_CLOCK)
|
39 | #define CLOCK_H cbi(DDRB, KB_CLOCK)
|
40 | #define CLOCK_LINE (PINB&(1<<KB_CLOCK))
|
41 |
|
42 | #define DATA_L sbi(DDRB, KB_DATA)
|
43 | #define DATA_H cbi(DDRB, KB_DATA)
|
44 | #define DATA_LINE (PINB&(1<<KB_DATA))
|
45 | //--
|
46 |
|
47 | #define _SHIFTDOWN 0x76 //esc 0x04
|
48 | #define _SHIFTUP 0x78 //f11 0x05
|
49 |
|
50 | unsigned int _eeprom_start EEMEM = 0x0000;
|
51 | unsigned int _eeprom_end EEMEM = 0x0000;
|
52 | unsigned int eeprom_start, eeprom_end;
|
53 |
|
54 | void putbyte(unsigned char b)
|
55 | {
|
56 | unsigned char m=0x80;
|
57 |
|
58 | while(m)
|
59 | {
|
60 | if(b&m) SDA_H; else SDA_L;
|
61 | I2C_CLOCK;
|
62 | m>>=1;
|
63 | }
|
64 |
|
65 | SDA_H;
|
66 | I2C_CLOCK;
|
67 | }
|
68 |
|
69 | unsigned char getbyte(unsigned char last)
|
70 | {
|
71 | unsigned char i, b=0;
|
72 |
|
73 | SDA_H;
|
74 |
|
75 | for(i=8; i; i--)
|
76 | {
|
77 | I2C_DELAY;
|
78 | SCL_H;
|
79 |
|
80 | b<<=1;
|
81 | if(SDA_LINE) b|=1;
|
82 |
|
83 | I2C_DELAY;
|
84 | SCL_L;
|
85 | }
|
86 |
|
87 | if(last) SDA_H; else SDA_L;
|
88 |
|
89 | I2C_CLOCK;
|
90 | SDA_H;
|
91 |
|
92 | return b;
|
93 | }
|
94 |
|
95 | #define KB_DELAY1 _delay_us(25);
|
96 | #define KB_DELAY2 _delay_us(15);
|
97 | #define KB_DELAY3 _delay_us(40);
|
98 |
|
99 | void send_kb(unsigned char byte)
|
100 | {
|
101 | unsigned char c=0, m=1;
|
102 | signed char i;
|
103 |
|
104 | while(!CLOCK_LINE) KB_DELAY3;
|
105 |
|
106 | for(i=-1; i<10; i++)
|
107 | {
|
108 | CLOCK_H;
|
109 |
|
110 | KB_DELAY1;
|
111 |
|
112 | switch(i)
|
113 | {
|
114 | case -1:
|
115 | DATA_L;
|
116 | break;
|
117 |
|
118 | case 8:
|
119 | if(c%2) DATA_L; else DATA_H;
|
120 | break;
|
121 |
|
122 | case 9:
|
123 | DATA_H;
|
124 | break;
|
125 |
|
126 | default:
|
127 | if(byte&m)
|
128 | {
|
129 | DATA_H;
|
130 | c++;
|
131 | } else DATA_L;
|
132 | m<<=1;
|
133 | }
|
134 |
|
135 | KB_DELAY2;
|
136 | CLOCK_L;
|
137 | KB_DELAY3;
|
138 | }
|
139 |
|
140 | CLOCK_H;
|
141 | }
|
142 |
|
143 | void clock_prescale(unsigned char x)
|
144 | {
|
145 | clock_prescale_set(x);
|
146 | }
|
147 |
|
148 | void dump_kb()
|
149 | {
|
150 | unsigned int a=eeprom_start;
|
151 | unsigned char byte;
|
152 |
|
153 | while(a!=eeprom_end)
|
154 | {
|
155 | if(a==EEPROM_SIZE) a=0;
|
156 |
|
157 | clock_prescale(clock_div_8);
|
158 | I2C_START;
|
159 | putbyte(EEPROM_ADDR&0xFE);
|
160 | putbyte(a>>8);
|
161 | putbyte(a);
|
162 |
|
163 | SCL_H;
|
164 | I2C_START;
|
165 | putbyte(EEPROM_ADDR|0x01);
|
166 | byte=getbyte(1);
|
167 | SDA_L;
|
168 | I2C_STOP;
|
169 | clock_prescale(clock_div_1);
|
170 |
|
171 | a++;
|
172 |
|
173 | switch(byte)
|
174 | {
|
175 | case _SHIFTUP:
|
176 | send_kb(0xf0);
|
177 |
|
178 | case _SHIFTDOWN:
|
179 | send_kb(0x12);
|
180 | break;
|
181 |
|
182 | default:
|
183 | send_kb(byte);
|
184 | send_kb(0xf0);
|
185 | send_kb(byte);
|
186 | }
|
187 | }
|
188 |
|
189 | send_kb(0xf0); send_kb(0x12);
|
190 | }
|
191 |
|
192 | void save_pointers()
|
193 | {
|
194 | eeprom_write_word(&_eeprom_start, eeprom_start);
|
195 | eeprom_busy_wait();
|
196 | eeprom_write_word(&_eeprom_end, eeprom_end);
|
197 | }
|
198 |
|
199 | void process_data(unsigned char data)
|
200 | {
|
201 | static unsigned char last=0, skip=0, is_up=0, count=0;
|
202 |
|
203 | if(data==0xf0) skip=0;
|
204 | if(data==0xe0) skip=1;
|
205 | if(skip) return;
|
206 |
|
207 | if(is_up)
|
208 | {
|
209 | is_up=0;
|
210 | last=0;
|
211 | if(data==0x12 || data==0x59) data=_SHIFTUP; else return;
|
212 | }
|
213 |
|
214 | if(data==0xf0) is_up=1;
|
215 |
|
216 | if(data>0x7d || data<0x0d || data==0x11) return;
|
217 |
|
218 | if(data==0x12 || data==0x59) data=_SHIFTDOWN;
|
219 |
|
220 | if(last==data) return;
|
221 | last=data;
|
222 |
|
223 | clock_prescale(clock_div_8);
|
224 | I2C_START;
|
225 | putbyte(EEPROM_ADDR&0xFE);
|
226 | putbyte(eeprom_end>>8);
|
227 | putbyte(eeprom_end);
|
228 | putbyte(data);
|
229 | SDA_L;
|
230 | I2C_STOP;
|
231 | clock_prescale(clock_div_1);
|
232 |
|
233 | if(++eeprom_end == EEPROM_SIZE) eeprom_end=0;
|
234 | if(eeprom_end==eeprom_start)
|
235 | if(++eeprom_start == EEPROM_SIZE) eeprom_start=0;
|
236 |
|
237 | if(++count==WRITE_PERIOD)
|
238 | {
|
239 | save_pointers();
|
240 | count=0;
|
241 | }
|
242 | }
|
243 |
|
244 | ISR(INT0_vect)
|
245 | {
|
246 | static unsigned char bit_cnt=0, data=0;
|
247 | unsigned char b;
|
248 |
|
249 | b=DATA_LINE;
|
250 |
|
251 | ++bit_cnt;
|
252 |
|
253 | if(bit_cnt==1)
|
254 | {
|
255 | data=0;
|
256 | if(b) bit_cnt=0;
|
257 | return;
|
258 | };
|
259 |
|
260 | if(bit_cnt==10) return;
|
261 |
|
262 | if(bit_cnt==11)
|
263 | {
|
264 | bit_cnt=0;
|
265 | process_data(data);
|
266 | return;
|
267 | };
|
268 |
|
269 | data>>=1;
|
270 | if(b) data|=0x80;
|
271 | }
|
272 |
|
273 | void main() __attribute__ ((noreturn));
|
274 |
|
275 | void main()
|
276 | {
|
277 | PORTB=1<<KB_SWITCH;
|
278 |
|
279 | GIMSK=(1<<6);
|
280 | MCUCR=0b00000010;
|
281 | GIFR=0x40;
|
282 |
|
283 | eeprom_start=eeprom_read_word(&_eeprom_start);
|
284 | eeprom_busy_wait();
|
285 | eeprom_end=eeprom_read_word(&_eeprom_end);
|
286 |
|
287 | sei();
|
288 |
|
289 | while(1)
|
290 | {
|
291 | if(!(PINB&(1<<KB_SWITCH)))
|
292 | {
|
293 | _delay_ms(4000);
|
294 | if((PINB&(1<<KB_SWITCH)))
|
295 | {
|
296 | cli();
|
297 | dump_kb();
|
298 | sei();
|
299 | }
|
300 | else
|
301 | {
|
302 | eeprom_start=eeprom_end=0;
|
303 | save_pointers();
|
304 | }
|
305 | }
|
306 | }
|
307 | }
|