Commit | Line | Data |
---|---|---|
54de37bf PH |
1 | /****************************************************************************** |
2 | * | |
3 | * Trennfix firmware - main.c | |
4 | * | |
5 | * Copyright (C) 2017 Philipp Hachtmann | |
6 | * | |
7 | * This program is free software: you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation, either version 3 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | * | |
20 | *****************************************************************************/ | |
21 | ||
22 | #include <stdio.h> | |
23 | #include <stdlib.h> | |
24 | #include <string.h> | |
25 | ||
26 | #include <avr/io.h> | |
27 | #include <avr/eeprom.h> | |
28 | #include <avr/interrupt.h> | |
29 | #include <avr/pgmspace.h> | |
30 | ||
31 | #include <util/delay.h> | |
32 | #include <stdint.h> | |
93cb14d4 | 33 | #include <mm/mm_switch.h> |
f12652df | 34 | #include <mm/mm_decode.h> |
93cb14d4 | 35 | #include <config/hardware.h> |
54de37bf | 36 | |
f12652df PH |
37 | uint8_t eeFooByte EEMEM = 123; |
38 | ||
70095677 PH |
39 | #define EE_MAGIC 0xab |
40 | ||
f12652df PH |
41 | FUSES = { |
42 | .low = FUSE_CKDIV8 & FUSE_SUT0 &\ | |
43 | FUSE_CKSEL3 & FUSE_CKSEL2 & FUSE_CKSEL1, | |
44 | .high = FUSE_SPIEN & FUSE_BODLEVEL1 & FUSE_BODLEVEL0 & FUSE_EESAVE, | |
45 | .extended = EFUSE_DEFAULT, | |
46 | }; | |
47 | ||
48 | void mm_key_cb(uint8_t decoder, uint8_t function, uint8_t key); | |
49 | void mm_drive_cb(uint8_t decoder, uint8_t function, uint8_t command); | |
50 | ||
70095677 PH |
51 | enum op_mode { |
52 | OM_MOMENTARY, /* on as long as "key on" pressed */ | |
53 | OM_DOUBLE, /* On off with "on" and "off" keys */ | |
54 | OM_TOGGLE, /* toggle on "key on" pressed */ | |
55 | OM_ERASED = 0xff /* EEPROM erased, need setup */ | |
56 | }; | |
57 | ||
58 | enum learn_mode { | |
59 | LM_OFF = 0, | |
dc41eb22 PH |
60 | LM_LEARN_ON_KEY, /* Learn primary key */ |
61 | LM_LEARN_OFF_KEY, /* Learn secondary key, relevant for OM_DOUBLE */ | |
62 | LM_LEARN_INITIAL, /* Learn initial pulse length, 10ms steps */ | |
63 | LM_LEARN_DUTY, /* Learn duty cycle 0-10 */ | |
64 | LM_LEARN_OP_MODE, /* Learn operation mode */ | |
65 | LM_EASY_WAIT_PRESS, /* Wait for key press to enter easy mode */ | |
66 | LM_EASY_WAIT_UP, /* Wait for end of key press */ | |
67 | LM_EASY_WAIT_TURN, /* Wait for loco 80 turn end */ | |
68 | LM_EASY_MODE, /* Easy config mode for PWM and initial kick */ | |
69 | LM_END, /* Only a label */ | |
f12652df | 70 | }; |
70095677 PH |
71 | |
72 | struct config { | |
73 | uint8_t magic; /* Magic value */ | |
74 | enum op_mode op_mode; | |
75 | uint8_t decoder_on; | |
76 | uint8_t key_on; | |
77 | uint8_t decoder_off; | |
78 | uint8_t key_off; | |
93cb14d4 | 79 | uint8_t initial_pulse; /* Lenghth of initial pulse in 10ms steps */ |
f12652df | 80 | uint8_t on_duty_cycle[15]; /* Duty cycle for on. 0-10 */ |
93cb14d4 | 81 | volatile enum learn_mode learn_mode; |
70095677 PH |
82 | }; |
83 | ||
f12652df | 84 | static uint8_t main_speed = 0; |
70095677 | 85 | static struct EEMEM config ee_config; |
93cb14d4 | 86 | static volatile struct config config; |
dc41eb22 PH |
87 | |
88 | static volatile uint8_t easy_mode = 0; | |
89 | static volatile uint8_t easy_mode_possible = 0; | |
90 | ||
91 | #ifndef USE_REGISTER_VARS | |
93cb14d4 | 92 | static volatile uint8_t drive_on = 0; |
dc41eb22 PH |
93 | #endif |
94 | ||
95 | /****************************************************************************** | |
96 | * | |
97 | * Some nice sounds to play on your coil | |
98 | * | |
99 | */ | |
100 | ||
101 | #define G 180 | |
102 | #define sekunde(g)(quinte((quinte(g)))*2) | |
103 | #define terz(g) ((g) * 4 / 5) | |
104 | #define kleine_terz(g) ((g) * 5 / 6) | |
105 | #define quarte(g) ((g) * 3 / 4) | |
106 | #define quinte(g) ((g) * 2 / 3) | |
107 | #define tt(g) ((g) * 32 / 45) | |
108 | #define septime(g) ((g) * 15 / 8) | |
109 | ||
110 | #if defined(WITH_SOUND) && defined(WITH_PWM) | |
111 | void play_tone(uint8_t divisor, uint8_t duration, uint8_t pause) | |
112 | { | |
113 | uint16_t c; | |
114 | TCCR1 = 0x8; | |
115 | OCR1C = divisor; | |
d0047978 PH |
116 | c = (divisor * 2) / 3; |
117 | OCR1B = c; | |
dc41eb22 PH |
118 | for (c = 0; c < duration - pause; c++) |
119 | _delay_ms(2); | |
d0047978 PH |
120 | TCCR1 = 0x6; |
121 | OCR1C = PWM_CYCLE; | |
122 | OCR1B = 12; | |
dc41eb22 PH |
123 | for (c = 0; c < pause; c++) |
124 | _delay_ms(2); | |
125 | TCCR1 = 0x6; | |
d0047978 PH |
126 | OCR1C = PWM_CYCLE; |
127 | OCR1B = PWM_CYCLE; | |
dc41eb22 PH |
128 | } |
129 | ||
130 | static void tone_enter(void) | |
131 | { | |
132 | play_tone((G), 70, 20); | |
133 | play_tone(terz(G), 70, 20); | |
134 | play_tone(quinte(G), 70, 20); | |
135 | play_tone(G/2, 100, 0); | |
136 | } | |
137 | ||
138 | static void tone_good(void) | |
139 | { | |
140 | play_tone(G, 150, 120); | |
141 | play_tone(terz(G), 100, 70); | |
142 | play_tone(tt(G), 100, 50); | |
143 | play_tone(quarte(terz((G))), 50, 0); | |
144 | play_tone(quinte(G), 150, 0); | |
f12652df | 145 | play_tone(terz(G), 100, 50); |
dc41eb22 PH |
146 | } |
147 | ||
148 | static void snd_on(void) | |
149 | { | |
150 | TCCR1 = 0x8; | |
151 | OCR1C = 120; | |
152 | OCR1B = 60; | |
153 | } | |
154 | ||
155 | static void snd_off(void) | |
156 | { | |
157 | TCCR1 = 0x6; | |
d0047978 PH |
158 | OCR1C = PWM_CYCLE; |
159 | OCR1B = PWM_CYCLE; | |
dc41eb22 PH |
160 | } |
161 | ||
162 | #else | |
163 | #define play_tone(...) | |
f12652df | 164 | #define tone_enter(...) {setpin(PIN_LED, 1); _delay_ms(500); setpin(PIN_LED, 0);} |
dc41eb22 PH |
165 | #define tone_good(...) |
166 | #define snd_on(...) | |
167 | #define snd_off(...) | |
168 | #endif | |
70095677 PH |
169 | |
170 | static void load_config(void) | |
54de37bf | 171 | { |
93cb14d4 | 172 | eeprom_read_block((uint8_t *)&config, &ee_config, sizeof(config)); |
54de37bf PH |
173 | } |
174 | ||
70095677 | 175 | static void save_config(void) |
54de37bf | 176 | { |
dc41eb22 | 177 | #ifdef WITH_EEPROM_UPDATE |
93cb14d4 PH |
178 | eeprom_update_block((uint8_t *)&config, &ee_config, sizeof(config)); |
179 | #else | |
180 | eeprom_write_block((uint8_t *)&config, &ee_config, sizeof(config)); | |
181 | #endif | |
54de37bf PH |
182 | } |
183 | ||
f12652df | 184 | void mm_pinchange_callback(void) |
d0047978 | 185 | { |
70095677 | 186 | static uint8_t btn_last = 0; |
56b25f8b | 187 | |
70095677 | 188 | if (BTN_PRESSED && !btn_last) { |
93cb14d4 PH |
189 | config.learn_mode++; |
190 | config.learn_mode %= LM_END; | |
70095677 PH |
191 | } |
192 | btn_last = BTN_PRESSED; | |
54de37bf PH |
193 | } |
194 | ||
56b25f8b PH |
195 | static uint8_t get_speed(uint8_t command) |
196 | { | |
f12652df PH |
197 | uint8_t b0, b2, b4, b6; |
198 | ||
199 | b0 = ((command & 0x80) != 0); | |
200 | b2 = ((command & 0x20) != 0); | |
201 | b4 = ((command & 0x8) != 0); | |
202 | b6 = ((command & 0x2) != 0); | |
203 | ||
204 | //if ((b9!= b2) || (b2 != b3) || (b3 != b4) || (b5 != b6) || (b7 != b8)) | |
56b25f8b | 205 | // return 0xff; |
f12652df PH |
206 | return (b0+ b2 * 2 + b4 * 4 +b6 * 8); |
207 | } | |
208 | ||
209 | enum mm2_command { | |
210 | CF_MM1 , | |
211 | CF_REVERSE, | |
212 | CF_FORWARD, | |
213 | CF_F1_ON, | |
214 | CF_F1_OFF, | |
215 | CF_F2_ON, | |
216 | CF_F2_OFF, | |
217 | CF_F3_ON, | |
218 | CF_F3_OFF, | |
219 | CF_F4_ON, | |
220 | CF_F4_OFF, | |
221 | }; | |
222 | ||
223 | #ifdef MM_USE_QUEUE | |
224 | static void dequeue_commands(void) | |
225 | { | |
226 | ||
227 | return; | |
228 | ||
229 | struct mm_command *cmd = mm_get(); | |
230 | if (!cmd) | |
231 | return; | |
232 | if (cmd->recmode != MM_FAST) | |
233 | return; | |
234 | if ((cmd->function & 0x3) != 0x3) | |
235 | return; | |
236 | // uint8_t loco = mm_lookup_decoder(cmd->address); | |
237 | ||
56b25f8b PH |
238 | } |
239 | ||
f12652df | 240 | #endif |
93cb14d4 | 241 | |
f12652df | 242 | void mm_drive_cb(uint8_t loco, uint8_t func_enc, uint8_t cmd_enc) |
56b25f8b | 243 | { |
f12652df PH |
244 | uint8_t b1, b3, b5, b7; |
245 | uint8_t fcode; | |
246 | ||
247 | /* Those three are decoded from fun and command */ | |
56b25f8b | 248 | uint8_t speed; |
f12652df PH |
249 | uint8_t function; |
250 | enum mm2_command mm2_command = CF_MM1; | |
dc41eb22 | 251 | static uint8_t alert_last = 0; |
f12652df PH |
252 | speed = get_speed(cmd_enc); |
253 | ||
254 | #ifdef MUELL | |
255 | goto mm2_done; // FIXME | |
256 | ||
257 | b1 = ((cmd_enc & 0x4) != 0); | |
258 | b3 = ((cmd_enc & 0x1) != 0); | |
259 | b5 = ((cmd_enc & 0x4) != 0); | |
260 | b7 = ((cmd_enc & 0x1) != 0); | |
261 | ||
262 | fcode = b1 * 8 + b3 * 4 + b5 *2 + b7; | |
263 | ||
264 | /* The ugly speed section */ | |
265 | if (speed < 8) { | |
266 | if (fcode == 0xb) { | |
267 | mm2_command = CF_REVERSE; | |
268 | goto mm2_done; | |
269 | } | |
270 | if (fcode == 0x5) { | |
271 | mm2_command = CF_FORWARD; | |
272 | goto mm2_done; | |
273 | } | |
274 | } else { | |
275 | if (fcode == 0xa) { | |
276 | mm2_command = CF_REVERSE; | |
277 | goto mm2_done; | |
278 | } | |
279 | if (fcode == 0x4) { | |
280 | mm2_command = CF_FORWARD; | |
281 | goto mm2_done; | |
282 | } | |
283 | } | |
284 | ||
285 | /* Special cases for f1-f4 commands */ | |
286 | if (fcode == 0xa) { | |
287 | switch(speed) { | |
288 | case 3: | |
289 | mm2_command = CF_F1_ON; | |
290 | goto mm2_done; | |
291 | case 4: | |
292 | mm2_command = CF_F2_ON; | |
293 | goto mm2_done; | |
294 | case 6: | |
295 | mm2_command = CF_F3_ON; | |
296 | goto mm2_done; | |
297 | case 7: | |
298 | mm2_command = CF_F4_ON; | |
299 | goto mm2_done; | |
300 | default: | |
301 | goto mm2_done; | |
302 | } | |
303 | } else if (fcode == 0x5) { | |
304 | switch(speed) { | |
305 | case 11: | |
306 | mm2_command = CF_F1_OFF; | |
307 | goto mm2_done; | |
308 | case 12: | |
309 | mm2_command = CF_F2_OFF; | |
310 | goto mm2_done; | |
311 | case 14: | |
312 | mm2_command = CF_F3_OFF; | |
313 | goto mm2_done; | |
314 | case 15: | |
315 | mm2_command = CF_F4_OFF; | |
316 | goto mm2_done; | |
317 | } | |
318 | } | |
319 | ||
320 | switch(fcode) { | |
321 | case 0xc: | |
322 | mm2_command = CF_F1_OFF; | |
323 | goto mm2_done; | |
324 | case 0xd: | |
325 | mm2_command = CF_F1_ON; | |
326 | goto mm2_done; | |
327 | ||
328 | case 0x2: | |
329 | mm2_command = CF_F2_OFF; | |
330 | goto mm2_done; | |
331 | case 0x3: | |
332 | mm2_command = CF_F2_ON; | |
333 | goto mm2_done; | |
334 | ||
335 | case 0x6: | |
336 | mm2_command = CF_F3_OFF; | |
337 | goto mm2_done; | |
338 | ||
339 | case 0x7: | |
340 | mm2_command = CF_F3_ON; | |
341 | goto mm2_done; | |
342 | ||
343 | case 0xe: | |
344 | mm2_command = CF_F4_OFF; | |
345 | goto mm2_done; | |
346 | ||
347 | case 0xf: | |
348 | mm2_command = CF_F4_ON; | |
349 | goto mm2_done; | |
350 | default: | |
351 | break; | |
352 | } | |
353 | mm2_done: | |
354 | if (loco == 34) { | |
355 | switch(mm2_command) { | |
356 | case CF_F3_ON: | |
357 | drive_on = 1; | |
358 | break; | |
359 | case CF_F3_OFF: | |
360 | drive_on = 0; | |
361 | break; | |
362 | default: | |
363 | break; | |
364 | } | |
365 | } | |
366 | #endif | |
367 | if (loco == config.decoder_on) { | |
368 | if (speed) | |
369 | speed = speed - 1; | |
370 | main_speed = speed; | |
371 | return; | |
372 | } | |
dc41eb22 PH |
373 | |
374 | switch(loco) { | |
375 | case 80: | |
376 | switch (config.learn_mode) { | |
377 | case LM_OFF: | |
378 | if (speed == 1) | |
379 | config.learn_mode = LM_EASY_WAIT_PRESS; | |
380 | break; | |
381 | case LM_EASY_MODE: | |
382 | if ((speed == 1) && (alert_last == 0)) { | |
383 | config.learn_mode = LM_OFF; | |
384 | save_config(); | |
385 | tone_good(); | |
93cb14d4 | 386 | } |
dc41eb22 | 387 | break; |
56b25f8b | 388 | |
dc41eb22 PH |
389 | case LM_EASY_WAIT_PRESS: |
390 | if (speed != 1) | |
391 | config.learn_mode = LM_OFF; | |
392 | break; | |
93cb14d4 | 393 | |
dc41eb22 PH |
394 | default: |
395 | break; | |
396 | } | |
397 | alert_last = (speed == 1); | |
398 | break; | |
d0047978 | 399 | |
dc41eb22 PH |
400 | case 50: |
401 | if (speed) | |
d0047978 PH |
402 | speed = speed - 1; |
403 | ||
dc41eb22 | 404 | if (config.learn_mode == LM_EASY_MODE) { |
93cb14d4 | 405 | config.initial_pulse = speed; |
56b25f8b | 406 | } |
dc41eb22 PH |
407 | break; |
408 | case 51: | |
d0047978 PH |
409 | if (speed) |
410 | speed = speed - 1; | |
411 | ||
dc41eb22 | 412 | if (config.learn_mode == LM_EASY_MODE) |
f12652df | 413 | config.on_duty_cycle[main_speed] = speed; |
dc41eb22 | 414 | break; |
56b25f8b PH |
415 | } |
416 | } | |
417 | ||
f12652df | 418 | void mm_key_cb(uint8_t decoder, uint8_t function, uint8_t raw_command) |
54de37bf | 419 | { |
70095677 | 420 | static uint8_t toggle_lock = 0; |
f12652df PH |
421 | uint8_t command; |
422 | ||
423 | static uint8_t last_raw = 0; | |
424 | static uint8_t last_fkey = 0; | |
425 | ||
426 | if ((function & 3) == 3) { /* F key hack! */ | |
427 | uint8_t diff; | |
428 | diff = last_raw ^ raw_command; | |
429 | if (diff) { | |
430 | if (diff & 0x80) | |
431 | command = 4; | |
432 | else if (diff & 0x20) | |
433 | command = 3; | |
434 | else if (diff & 0x8) | |
435 | command = 2; | |
436 | else | |
437 | command = 1; | |
438 | command |= 0x80; | |
439 | if ((command == config.key_on) | |
440 | && (last_raw & ~raw_command)) | |
441 | command = 0; | |
442 | last_raw = raw_command; | |
443 | } else { | |
444 | return; | |
445 | } | |
446 | } else { | |
447 | command = mm_lookup_key(raw_command); | |
448 | } | |
dc41eb22 | 449 | |
93cb14d4 | 450 | switch(config.learn_mode) { |
70095677 PH |
451 | case LM_OFF: |
452 | default: | |
453 | if ((decoder == config.decoder_on) && | |
454 | (command == config.key_on)) { /* Primary key pressed */ | |
455 | switch(config.op_mode) { | |
456 | case OM_MOMENTARY: | |
457 | case OM_DOUBLE: | |
dc41eb22 | 458 | drive_on = 1; |
70095677 PH |
459 | break; |
460 | case OM_TOGGLE: | |
461 | if (!toggle_lock) { | |
dc41eb22 | 462 | drive_on = ~drive_on; |
70095677 PH |
463 | toggle_lock = 1; |
464 | } | |
465 | break; | |
466 | default: | |
467 | break; | |
468 | } | |
469 | } | |
70095677 | 470 | if ((decoder == config.decoder_on) && |
7c08d02a | 471 | (command == 0)) { /* Primary key released */ |
70095677 PH |
472 | switch(config.op_mode) { |
473 | case OM_MOMENTARY: | |
dc41eb22 | 474 | drive_on = 0; |
70095677 PH |
475 | break; |
476 | case OM_TOGGLE: | |
477 | toggle_lock = 0; | |
478 | break; | |
479 | default: | |
480 | break; | |
481 | } | |
482 | } | |
dc41eb22 PH |
483 | break; |
484 | ||
485 | case LM_EASY_WAIT_PRESS: | |
486 | if ((decoder == config.decoder_on) && | |
487 | (command == config.key_on)) | |
488 | config.learn_mode = LM_EASY_WAIT_UP; | |
489 | return; | |
490 | ||
491 | case LM_EASY_WAIT_UP: | |
492 | if ((decoder == config.decoder_on) && | |
493 | (command == 0)) { | |
494 | config.learn_mode = LM_EASY_MODE; | |
495 | tone_enter(); | |
496 | } | |
497 | return; | |
f12652df | 498 | |
93cb14d4 | 499 | #ifdef HANDLE_OFF_KEY |
54de37bf | 500 | |
70095677 PH |
501 | if ((decoder == config.decoder_off) && |
502 | (command == config.key_off)) { /* Secondary "off" key pressed */ | |
503 | switch(config.op_mode) { | |
504 | case OM_DOUBLE: | |
505 | drive_on = 0; | |
506 | break; | |
507 | case OM_TOGGLE: | |
508 | case OM_MOMENTARY: | |
509 | default: | |
510 | break; | |
70095677 PH |
511 | } |
512 | } | |
93cb14d4 | 513 | #endif |
70095677 | 514 | break; |
f12652df | 515 | |
70095677 PH |
516 | case LM_LEARN_ON_KEY: |
517 | if (command) { | |
518 | config.decoder_on = decoder; | |
519 | config.key_on = command; | |
70095677 | 520 | if (config.op_mode == OM_DOUBLE) |
93cb14d4 | 521 | config.learn_mode = LM_LEARN_OFF_KEY; |
70095677 | 522 | else |
93cb14d4 PH |
523 | config.learn_mode = LM_OFF; |
524 | save_config(); | |
70095677 PH |
525 | } |
526 | break; | |
93cb14d4 | 527 | #ifdef LEARN_ADVANCED |
70095677 PH |
528 | case LM_LEARN_OFF_KEY: |
529 | if (command) { | |
530 | config.decoder_off = decoder; | |
531 | config.key_off = command; | |
93cb14d4 | 532 | config.learn_mode = LM_OFF; |
70095677 | 533 | save_config(); |
70095677 PH |
534 | } |
535 | break; | |
f12652df | 536 | |
70095677 PH |
537 | case LM_LEARN_INITIAL: |
538 | if (drive_on) { | |
539 | if (command == 0) | |
540 | drive_on = 0; | |
f12652df | 541 | |
70095677 PH |
542 | } else { |
543 | switch(command) { | |
544 | case 1: | |
545 | if (config.initial_pulse >= 10) | |
546 | config.initial_pulse -= 10; | |
f12652df | 547 | else |
70095677 PH |
548 | config.initial_pulse = 0; |
549 | save_config(); | |
550 | drive_on = 1; | |
551 | break; | |
552 | case 2: | |
553 | if (config.initial_pulse <= 245) | |
554 | config.initial_pulse += 10; | |
555 | else | |
556 | config.initial_pulse = 255; | |
557 | save_config(); | |
558 | drive_on = 1; | |
559 | break; | |
560 | default: | |
561 | break; | |
562 | } | |
563 | } | |
564 | break; | |
54de37bf | 565 | |
70095677 PH |
566 | case LM_LEARN_DUTY: |
567 | if (drive_on) { | |
568 | if (command == 0) | |
569 | drive_on = 0; | |
570 | } else { | |
571 | switch(command) { | |
572 | case 1: | |
573 | if (config.on_duty_cycle > 0) | |
574 | config.on_duty_cycle -= 1; | |
575 | save_config(); | |
576 | drive_on = 1; | |
577 | break; | |
578 | case 2: | |
579 | if (config.on_duty_cycle < 10) | |
580 | config.on_duty_cycle += 1; | |
581 | save_config(); | |
582 | drive_on = 1; | |
583 | break; | |
584 | default: | |
585 | break; | |
586 | } | |
587 | } | |
588 | break; | |
f12652df | 589 | |
70095677 PH |
590 | case LM_LEARN_OP_MODE: |
591 | switch(command) { | |
592 | case 1: | |
593 | config.op_mode = OM_MOMENTARY; | |
594 | save_config(); | |
93cb14d4 | 595 | config.learn_mode = LM_OFF; |
70095677 PH |
596 | break; |
597 | case 3: | |
598 | config.op_mode = OM_DOUBLE; | |
599 | save_config(); | |
93cb14d4 | 600 | config.learn_mode = LM_OFF; |
70095677 PH |
601 | break; |
602 | case 5: | |
603 | config.op_mode = OM_TOGGLE; | |
604 | save_config(); | |
93cb14d4 | 605 | config.learn_mode = LM_OFF; |
70095677 PH |
606 | break; |
607 | default: | |
608 | break; | |
609 | } | |
610 | break; | |
93cb14d4 | 611 | #endif |
54de37bf PH |
612 | } |
613 | } | |
614 | ||
615 | ||
54de37bf PH |
616 | /****************************************************************************** |
617 | * | |
618 | * main() - The main routine | |
619 | * | |
620 | */ | |
7c08d02a | 621 | void shift(uint8_t mu); |
54de37bf | 622 | |
f12652df PH |
623 | #ifdef DEBUG_DRIVE_LED |
624 | #define MON_LED(val) setpin(PIN_LED, val) | |
625 | #else | |
626 | #define MON_LED(val) | |
627 | #endif | |
628 | ||
dc41eb22 | 629 | #ifdef WITH_PWM |
f12652df PH |
630 | #define DRIVE_OFF {OCR1B = PWM_CYCLE; MON_LED(0);} |
631 | #define DRIVE_ON {OCR1B = PWM_CYCLE - config.on_duty_cycle[main_speed]; \ | |
632 | MON_LED(1);} | |
633 | #define DRIVE_FULL {OCR1B = 0; MON_LED(1);} | |
dc41eb22 | 634 | #else |
f12652df PH |
635 | #define DRIVE_OFF {setpin(PIN_DRIVE, 0); MON_LED(0);} |
636 | #define DRIVE_ON {setpin(PIN_DRIVE, 1); MON_LED(1);} | |
637 | #define DRIVE_FULL {setpin(PIN_DRIVE, 1); MON_LED(1);} | |
dc41eb22 PH |
638 | #endif |
639 | ||
54de37bf | 640 | int main(void) { |
dc41eb22 PH |
641 | uint16_t i; |
642 | ||
643 | #ifdef WITH_INITIAL_PULSE | |
70095677 PH |
644 | uint8_t drive_last = 0; |
645 | uint8_t drive_slope = 0; | |
dc41eb22 PH |
646 | #endif |
647 | ||
dc41eb22 PH |
648 | #ifdef USE_REGISTER_VARS |
649 | drive_on = 0; | |
650 | #endif | |
7c08d02a | 651 | mm_init(); |
70095677 | 652 | load_config(); |
56b25f8b | 653 | setup_hw(); |
dc41eb22 | 654 | |
f12652df PH |
655 | while(0) { |
656 | setpin(PIN_LED, 1); | |
657 | _delay_ms(2); | |
658 | _delay_ms(2); | |
659 | trigger(); | |
660 | sei(); | |
661 | } | |
dc41eb22 | 662 | if (config.magic != EE_MAGIC) { |
70095677 PH |
663 | config.magic = EE_MAGIC; |
664 | config.op_mode = OM_MOMENTARY; | |
56b25f8b PH |
665 | config.decoder_on = 1; |
666 | config.key_on = 1; | |
70095677 PH |
667 | config.decoder_off = 1; |
668 | config.key_off = 2; | |
669 | config.initial_pulse = 10; | |
f12652df | 670 | config.on_duty_cycle[0] = 5; |
93cb14d4 | 671 | config.learn_mode = LM_LEARN_ON_KEY; |
70095677 | 672 | } |
54de37bf | 673 | sei(); |
54de37bf | 674 | while (1) { |
f12652df PH |
675 | #ifdef MM_USE_QUEUE |
676 | dequeue_commands(); | |
677 | #endif | |
93cb14d4 PH |
678 | drive_start: |
679 | ||
dc41eb22 | 680 | #ifdef WITH_INITIAL_PULSE |
70095677 | 681 | cli(); |
dc41eb22 | 682 | if (drive_on && !drive_last) |
70095677 PH |
683 | drive_slope = 1; |
684 | else | |
685 | drive_slope = 0; | |
dc41eb22 | 686 | drive_last = drive_on; |
70095677 | 687 | sei(); |
dc41eb22 PH |
688 | #endif |
689 | if (drive_on) { | |
56b25f8b | 690 | |
dc41eb22 | 691 | #ifdef WITH_INITIAL_PULSE |
70095677 | 692 | if (drive_slope) { |
dc41eb22 | 693 | DRIVE_FULL; |
70095677 | 694 | for (i = 0; i < config.initial_pulse; i++) { |
dc41eb22 | 695 | _delay_ms(5); |
70095677 | 696 | } |
af5fd980 | 697 | } |
dc41eb22 PH |
698 | #endif |
699 | DRIVE_ON; | |
f12652df | 700 | |
54de37bf | 701 | } else { |
dc41eb22 PH |
702 | DRIVE_OFF; |
703 | ||
704 | if (!config.learn_mode || | |
705 | config.learn_mode > LM_LEARN_OP_MODE) | |
70095677 | 706 | continue; |
54de37bf | 707 | |
93cb14d4 | 708 | for (i = 0; i < config.learn_mode; i++) { |
70095677 | 709 | setpin(PIN_LED, 1); |
dc41eb22 | 710 | snd_on(); |
93cb14d4 | 711 | _delay_ms(10); |
70095677 | 712 | setpin(PIN_LED, 0); |
dc41eb22 PH |
713 | snd_off(); |
714 | if (drive_on) goto drive_start; | |
93cb14d4 | 715 | _delay_ms(135); |
dc41eb22 | 716 | if (drive_on) goto drive_start; |
70095677 | 717 | } |
93cb14d4 | 718 | for (i = 0; i < 15 - config.learn_mode; i++) { |
dc41eb22 | 719 | if (drive_on) goto drive_start; |
93cb14d4 | 720 | _delay_ms(70); |
70095677 PH |
721 | } |
722 | } | |
f12652df PH |
723 | // MCUCR |= _BV(SE); |
724 | // sleep(); | |
54de37bf PH |
725 | } |
726 | return 0; | |
727 | } | |
728 | ||
729 | /****************************************************************************** | |
730 | * The end :-) | |
731 | */ |