1 /******************************************************************************
3 * Trennfix firmware - main.c
5 * Copyright (C) 2017 Philipp Hachtmann
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.
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.
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/>.
20 *****************************************************************************/
27 #include <avr/eeprom.h>
28 #include <avr/interrupt.h>
29 #include <avr/pgmspace.h>
31 #include <util/delay.h>
34 #include "mm_switch.h"
37 // #define DEBUG_TIMEOUT
39 #define MON_TIMEOUT(val) setpin(DRIVE, val)
41 #define MON_TIMEOUT(xx) ({0;})
46 static void trigger(void)
54 OM_MOMENTARY
, /* on as long as "key on" pressed */
55 OM_DOUBLE
, /* On off with "on" and "off" keys */
56 OM_TOGGLE
, /* toggle on "key on" pressed */
57 OM_ERASED
= 0xff /* EEPROM erased, need setup */
62 LM_LEARN_ON_KEY
, /* Learn primary key */
63 LM_LEARN_OFF_KEY
, /* Learn secondary key, relevant for OM_DOUBLE */
64 LM_LEARN_INITIAL
, /* Learn initial pulse length, 10ms steps */
65 LM_LEARN_DUTY
, /* Learn duty cycle 0-10 */
66 LM_LEARN_OP_MODE
, /* Learn operation mode */
67 LM_END
, /* Only a label */
71 uint8_t magic
; /* Magic value */
77 uint8_t initial_pulse
; /* Lenghth of initial pulse in 10ms steps */
78 uint8_t on_duty_cycle
; /* Duty cycle for on. 0-10 */
81 static struct EEMEM config ee_config
;
82 static struct config config
;
83 static volatile enum learn_mode learn_mode
= LM_OFF
;
85 static void load_config(void)
87 eeprom_read_block(&config
, &ee_config
, sizeof(config
));
90 static void save_config(void)
92 eeprom_update_block(&config
, &ee_config
, sizeof(config
));
95 static volatile uint8_t drive_on
= 0;
98 static uint8_t btn_last
= 0;
100 mm_pinchange_handler();
102 if (BTN_PRESSED
&& !btn_last
) {
104 learn_mode
%= LM_END
;
106 btn_last
= BTN_PRESSED
;
109 static uint8_t get_speed(uint8_t command
)
111 uint8_t b1
, b2
, b3
, b4
, b5
, b6
, b7
, b8
;
112 b1
= ((command
& 0x80) != 0);
113 b2
= ((command
& 0x40) != 0);
114 b3
= ((command
& 0x20) != 0);
115 b4
= ((command
& 0x10) != 0);
116 b5
= ((command
& 0x8) != 0);
117 b6
= ((command
& 0x4) != 0);
118 b7
= ((command
& 0x2) != 0);
119 b8
= ((command
& 0x1) != 0);
121 //if ((b1 != b2) || (b2 != b3) || (b3 != b4) || (b5 != b6) || (b7 != b8))
124 return (b1
+ b3
*2 + b5
*4 +b7
*8);
127 void mm_switch_drive(uint8_t decoder
, uint8_t function
, uint8_t command
)
129 static uint8_t seen_before
= 0;
134 // if (decoder == 100)
137 if ((decoder
== 100) && (function
== 0) && (command
== 0xc0)) {
143 speed
= get_speed(command
);
144 static uint8_t itsme
= 0;
161 speed
= get_speed(command
);
163 if (speed
>= 1) speed
-= 1;
165 config
.on_duty_cycle
= speed
;
167 config
.on_duty_cycle
= 14;
172 void mm_switch_command(uint8_t decoder
, uint8_t command
)
174 static uint8_t toggle_lock
= 0;
179 if ((decoder
== config
.decoder_on
) &&
180 (command
== config
.key_on
)) { /* Primary key pressed */
181 switch(config
.op_mode
) {
188 drive_on
= !drive_on
;
197 if ((decoder
== config
.decoder_on
) &&
198 (command
== 0)) { /* Primary key released */
199 switch(config
.op_mode
) {
211 if ((decoder
== config
.decoder_off
) &&
212 (command
== config
.key_off
)) { /* Secondary "off" key pressed */
213 switch(config
.op_mode
) {
225 case LM_LEARN_ON_KEY
:
227 config
.decoder_on
= decoder
;
228 config
.key_on
= command
;
230 if (config
.op_mode
== OM_DOUBLE
)
231 learn_mode
= LM_LEARN_OFF_KEY
;
237 #ifdef LEARN_THE_STUFF
238 case LM_LEARN_OFF_KEY
:
240 config
.decoder_off
= decoder
;
241 config
.key_off
= command
;
247 case LM_LEARN_INITIAL
:
255 if (config
.initial_pulse
>= 10)
256 config
.initial_pulse
-= 10;
258 config
.initial_pulse
= 0;
263 if (config
.initial_pulse
<= 245)
264 config
.initial_pulse
+= 10;
266 config
.initial_pulse
= 255;
283 if (config
.on_duty_cycle
> 0)
284 config
.on_duty_cycle
-= 1;
289 if (config
.on_duty_cycle
< 10)
290 config
.on_duty_cycle
+= 1;
300 case LM_LEARN_OP_MODE
:
303 config
.op_mode
= OM_MOMENTARY
;
308 config
.op_mode
= OM_DOUBLE
;
313 config
.op_mode
= OM_TOGGLE
;
326 /******************************************************************************
328 * main() - The main routine
333 // uint8_t learn_mode_off;
334 uint8_t drive_last
= 0;
335 uint8_t drive_slope
= 0;
341 if ((config
.op_mode
== OM_ERASED
) || (config
.magic
!= EE_MAGIC
)) {
342 config
.magic
= EE_MAGIC
;
343 config
.op_mode
= OM_MOMENTARY
;
344 config
.decoder_on
= 1;
346 config
.decoder_off
= 1;
348 config
.initial_pulse
= 10;
349 config
.on_duty_cycle
= 5;
350 learn_mode
= LM_LEARN_ON_KEY
;
359 if (!drive_last
&& drive_on
)
363 drive_last
= drive_on
;
369 for (i
= 0; i
< config
.initial_pulse
; i
++) {
370 setpin(PIN_DRIVE
, 1);
378 for (i
= 0; i
< config
.on_duty_cycle
; i
++) {
379 setpin(PIN_DRIVE
, drive_on
);
382 for (i
= 0; i
< (14 - config
.on_duty_cycle
); i
++) {
383 setpin(PIN_DRIVE
, 0);
388 setpin(PIN_DRIVE
, 1);
392 setpin(PIN_DRIVE
, 0);
396 //learn_mode_off = !learn_mode;
398 //if (drive_on || (learn_mode && learn_mode_off))
401 for (i
= 0; i
< learn_mode
; i
++) {
407 //if (drive_on || (learn_mode && learn_mode_off))
409 //if (drive_on || (learn_mode && learn_mode_off))
412 for (i
= 0; i
< 15 - learn_mode
; i
++) {
413 //if (drive_on || (learn_mode && learn_mode_off))
417 //if (drive_on || (learn_mode && learn_mode_off))
427 /******************************************************************************