trennfix/sw: Nice, keep! Good!
[eisenbahn.git] / trennfix / sw / src / main.c
index 47d051d34dacce3e486d21da22a6256932cea3d7..c61741e6b22632ba2ac997c58a2a33952dffb54f 100644 (file)
@@ -44,12 +44,16 @@ enum op_mode {
 
 enum learn_mode {
        LM_OFF = 0,
-       LM_LEARN_ON_KEY,   /* Learn primary key                           */
-       LM_LEARN_OFF_KEY,  /* Learn secondary key, relevant for OM_DOUBLE */
-       LM_LEARN_INITIAL,  /* Learn initial pulse length, 10ms steps      */
-       LM_LEARN_DUTY,     /* Learn duty cycle 0-10                       */
-       LM_LEARN_OP_MODE,  /* Learn operation mode                        */
-       LM_END,            /* Only a label                                */
+       LM_LEARN_ON_KEY,     /* Learn primary key                           */
+       LM_LEARN_OFF_KEY,    /* Learn secondary key, relevant for OM_DOUBLE */
+       LM_LEARN_INITIAL,    /* Learn initial pulse length, 10ms steps      */
+       LM_LEARN_DUTY,       /* Learn duty cycle 0-10                       */
+       LM_LEARN_OP_MODE,    /* Learn operation mode                        */
+       LM_EASY_WAIT_PRESS,  /* Wait for key press to enter easy mode       */
+       LM_EASY_WAIT_UP,     /* Wait for end of key press                   */
+       LM_EASY_WAIT_TURN,   /* Wait for loco 80 turn end                   */
+       LM_EASY_MODE,        /* Easy config mode for PWM and initial kick   */
+       LM_END,              /* Only a label                                */
 };             
 
 struct config {
@@ -66,7 +70,86 @@ struct config {
 
 static struct EEMEM config ee_config;
 static volatile struct config config;
+
+static volatile uint8_t easy_mode = 0;
+static volatile uint8_t easy_mode_possible = 0;
+
+#ifndef USE_REGISTER_VARS
 static volatile uint8_t drive_on = 0;
+#endif
+
+/******************************************************************************
+ *
+ * Some nice sounds to play on your coil
+ *
+ */
+
+#define G 180
+#define sekunde(g)(quinte((quinte(g)))*2)
+#define terz(g) ((g) * 4 / 5)
+#define kleine_terz(g) ((g) * 5 / 6)
+#define quarte(g) ((g) * 3 / 4)
+#define quinte(g) ((g) * 2 / 3)
+#define tt(g) ((g) * 32 / 45)
+#define septime(g) ((g) * 15 / 8)
+
+#if defined(WITH_SOUND) && defined(WITH_PWM)
+void play_tone(uint8_t divisor, uint8_t duration, uint8_t pause)
+{
+       uint16_t c;
+       TCCR1 = 0x8;
+       OCR1C = divisor;
+       OCR1B = divisor / 2;
+       for (c = 0; c < duration - pause; c++)
+               _delay_ms(2);
+       OCR1B = 255;
+       OCR1C = 14;
+       for (c = 0; c < pause; c++)
+               _delay_ms(2);
+       TCCR1 = 0x6;
+       OCR1C = 14;
+       OCR1B = 14;
+}
+
+static void tone_enter(void)
+{
+       play_tone((G), 70, 20);
+       play_tone(terz(G), 70, 20);
+       play_tone(quinte(G), 70, 20);
+       play_tone(G/2, 100, 0);
+}
+
+static void tone_good(void)
+{
+       play_tone(G, 150, 120);
+       play_tone(terz(G), 100, 70);
+       play_tone(tt(G), 100, 50);
+       play_tone(quarte(terz((G))), 50, 0);
+       play_tone(quinte(G), 150, 0);
+       play_tone(terz(G), 100, 50);            
+}
+
+static void snd_on(void)
+{
+       TCCR1 = 0x8;
+       OCR1C = 120;
+       OCR1B = 60;
+}
+
+static void snd_off(void)
+{
+       TCCR1 = 0x6;
+       OCR1C = 14;
+       OCR1B = 14;
+}
+
+#else
+#define play_tone(...)
+#define tone_enter(...)
+#define tone_good(...)
+#define snd_on(...)
+#define snd_off(...)
+#endif
 
 static void load_config(void)
 {
@@ -75,15 +158,13 @@ static void load_config(void)
 
 static void save_config(void)
 {
-#ifdef USE_EEPROM_UPDATE
+#ifdef WITH_EEPROM_UPDATE
        eeprom_update_block((uint8_t *)&config, &ee_config, sizeof(config));
 #else
        eeprom_write_block((uint8_t *)&config, &ee_config, sizeof(config));
 #endif
 }
 
-
-
 ISR(PCINT0_vect){
        static uint8_t btn_last = 0;
 
@@ -101,13 +182,9 @@ static uint8_t get_speed(uint8_t command)
        uint8_t b1,  b3, b5, b7;
                
        b1 = ((command & 0x80) != 0);
-       //      b2 = ((command & 0x40) != 0);
        b3 = ((command & 0x20) != 0);
-       //      b4 = ((command & 0x10) != 0);
        b5 = ((command & 0x8) != 0);
-       //      b6 = ((command & 0x4) != 0);
        b7 = ((command & 0x2) != 0);
-       //      b8 = ((command & 0x1) != 0);
        
        //if ((b1 != b2) || (b2 != b3) || (b3 != b4) || (b5 != b6) || (b7 != b8))
        //      return 0xff;
@@ -115,96 +192,58 @@ static uint8_t get_speed(uint8_t command)
        return (b1 + b3*2 + b5*4 +b7*8);
 }
 
-#ifdef INTERPRET_DRIVE_COMMANDS
 
-void mm_switch_drive(uint8_t decoder, uint8_t function, uint8_t command)
+void mm_switch_drive(uint8_t loco, uint8_t function, uint8_t command)
 {
-       static uint8_t seen_before = 0;
        uint8_t speed;
-
-       if (!seen_before) {
-               if ((decoder == 80) && (function == 0) && (command == 0xc0)) {
-                       config.learn_mode = 1;
-                       save_config();
-               }
-       }
-       seen_before = 1;
-       
        speed = get_speed(command);
-       static uint8_t itsme = 0;
-
-       if (config.learn_mode) {
-               if (decoder == 70) {
-                       if (speed == 1) {
-                               itsme = 1;
-                       drive_on = 1;
-                       }else {
-                               if (itsme) {
-                                       drive_on = 0;
-                                       itsme = 0;
-                               }
-                       }
-               }
-               
-               if (decoder == 33) {
-                       if (speed != 0xff) {
-                               if (speed >= 1) speed -= 1;
-                               if (speed <= 14)
-                                       config.on_duty_cycle = speed;
-                               else
-                                       config.on_duty_cycle = 14;
-                               
-                       }
-               }
-               
-               if (decoder == 32) {
-                       if (speed != 0xff) {
-                               config.initial_pulse = speed;
+       static uint8_t alert_last = 0;
+
+       switch(loco) {
+       case 80:
+               switch (config.learn_mode) {
+               case LM_OFF:
+                       if (speed == 1)
+                               config.learn_mode = LM_EASY_WAIT_PRESS;
+                       break;
+               case LM_EASY_MODE:
+                       if ((speed == 1) && (alert_last == 0)) {
+                               config.learn_mode = LM_OFF;
+                               save_config();
+                               tone_good();
                        }
-               }
-               
-               if (decoder == 31 && command == 0xc0)
-                       save_config();
-       }
-}
-
-#else
-#ifdef INTERPRET_DRIVE_SIMPLE
+                       break;
 
-static volatile uint8_t current_loco;
+               case LM_EASY_WAIT_PRESS:
+                       if (speed != 1)
+                           config.learn_mode = LM_OFF;
+                       break;
 
-void mm_switch_drive(uint8_t decoder, uint8_t function, uint8_t command)
-{
-       uint8_t speed;
-       speed = get_speed(command);
-       current_loco = decoder;
-       if (speed != 0xff) {
-               if (decoder == 50) {
-                       setpin(PIN_LED, drive_on = function & 3);
+               default:
+                       break;
+               }
+               alert_last = (speed == 1);
+               break;
+       case 50:
+               if (speed)
+                       speed -= 1;
+               
+               if (config.learn_mode == LM_EASY_MODE) {
                        config.initial_pulse = speed;
-               } else if (decoder == 51) {
-                       if (speed >= 1) speed -= 1;
-                       if (speed <= 14)
-                               config.on_duty_cycle = speed;
-                       else
-                               config.on_duty_cycle = 14;
-               } else if (decoder == 52) {
-                       static uint8_t last_speed;
-                       if (speed == 1 && last_speed != 1)
-                               save_config();
-                       last_speed = speed;
-                       
                }
+               break;
+       case 51:
+               if (config.learn_mode == LM_EASY_MODE)
+                       config.on_duty_cycle = speed;
+               break;
        }
+       
 }
 
-#endif
-#endif
-static volatile uint8_t switch_on = 0;
-
 void mm_switch_command(uint8_t decoder, uint8_t command)
 {
        static uint8_t toggle_lock = 0;
+
        switch(config.learn_mode) {
 
        case LM_OFF:
@@ -214,13 +253,11 @@ void mm_switch_command(uint8_t decoder, uint8_t command)
                        switch(config.op_mode) {
                        case OM_MOMENTARY:
                        case OM_DOUBLE:
-                               if (!switch_on && current_loco == 52)
-                                       save_config();
-                               switch_on = 1;
+                               drive_on = 1;
                                break;
                        case OM_TOGGLE:
                                if (!toggle_lock) {
-                                       drive_on = !drive_on;
+                                       drive_on = ~drive_on;
                                        toggle_lock = 1;
                                }
                                break;
@@ -228,12 +265,11 @@ void mm_switch_command(uint8_t decoder, uint8_t command)
                                break;
                        }
                }
-
                if ((decoder == config.decoder_on) &&
                    (command == 0)) {  /* Primary key released */
                        switch(config.op_mode) {
                        case OM_MOMENTARY:
-                               switch_on = 0;
+                               drive_on = 0;
                                break;
                        case OM_TOGGLE:
                                toggle_lock = 0;
@@ -242,6 +278,22 @@ void mm_switch_command(uint8_t decoder, uint8_t command)
                                break;
                        }
                }
+               break;
+
+       case LM_EASY_WAIT_PRESS:
+               if ((decoder == config.decoder_on) &&
+                   (command == config.key_on))
+                       config.learn_mode = LM_EASY_WAIT_UP;
+               return;
+
+       case LM_EASY_WAIT_UP:
+               if ((decoder == config.decoder_on) &&
+                   (command == 0)) {
+                       config.learn_mode = LM_EASY_MODE;
+                       tone_enter();
+               }
+               return;
+       
 #ifdef HANDLE_OFF_KEY
 
                if ((decoder == config.decoder_off) &&
@@ -366,18 +418,33 @@ void mm_switch_command(uint8_t decoder, uint8_t command)
  */
 void shift(uint8_t mu);
 
+#ifdef WITH_PWM
+#define DRIVE_OFF  {OCR1B = 14;}
+#define DRIVE_ON   {OCR1B = 14 - config.on_duty_cycle;}
+#define DRIVE_FULL {OCR1B = 0;}
+#else
+#define DRIVE_OFF  {setpin(PIN_DRIVE, 0);}
+#define DRIVE_ON   {setpin(PIN_DRIVE, 1); setpin(PIN_LED, 1);}
+#define DRIVE_FULL {setpin(PIN_DRIVE, 1); setpin(PIN_LED, 0);}
+#endif
+
 int main(void) {
-       uint8_t learn_mode_off;
+       uint16_t i;
+
+#ifdef WITH_INITIAL_PULSE
        uint8_t drive_last = 0;
        uint8_t drive_slope = 0;
-       uint8_t i;
-       uint8_t output_on;
+#endif
+
 
+#ifdef USE_REGISTER_VARS
+       drive_on = 0;
+#endif
        mm_init();
        load_config();
        setup_hw();
-       
-       if ((config.op_mode == OM_ERASED) || (config.magic != EE_MAGIC)) {
+
+       if (config.magic != EE_MAGIC) {
                config.magic = EE_MAGIC;
                config.op_mode = OM_MOMENTARY;
                config.decoder_on = 1;
@@ -388,81 +455,59 @@ int main(void) {
                config.on_duty_cycle = 5;
                config.learn_mode = LM_LEARN_ON_KEY;
        }
-       drive_on = 0;
        sei();
 
-
-       //setpin(PIN_LED,1 );
-       //_delay_ms(400);
-       //setpin(PIN_LED,0 );
        while (1) {
-               
        drive_start:
 
-               output_on = drive_on || switch_on;
+#ifdef WITH_INITIAL_PULSE
                cli();
-               if (!drive_last && output_on)
+               if (drive_on && !drive_last)
                        drive_slope = 1;
                else
                        drive_slope = 0;
-               drive_last = output_on;
+               drive_last = drive_on;
                sei();
+#endif
+               if (drive_on) {
 
-               if (output_on) {
+#ifdef WITH_INITIAL_PULSE
                        if (drive_slope) {
+                               DRIVE_FULL;
                                for (i = 0; i < config.initial_pulse; i++) {
-                                       setpin(PIN_DRIVE, 1);   
-                                       _delay_ms(20);
+                                       _delay_ms(5);
                                }
                        }
-
-                       for (i = 0; i < config.on_duty_cycle; i++) {
-                               setpin(PIN_DRIVE, output_on);
-                               _delay_us(1);
-                       }
-                       for (i = 0; i < (14 - config.on_duty_cycle); i++) {
-                               setpin(PIN_DRIVE, 0);
-                               _delay_us(1);
-                       }
-
+#endif
+                       DRIVE_ON;
+               
                } else {
-                       setpin(PIN_DRIVE, 0);
-                       if (!config.learn_mode)
+                       DRIVE_OFF;
+
+                       if (!config.learn_mode ||
+                           config.learn_mode > LM_LEARN_OP_MODE)
                                continue;
 
-                       learn_mode_off = !config.learn_mode;
-                       
-                       if (output_on || (config.learn_mode && learn_mode_off))
-                               goto drive_start;
 
                        for (i = 0; i < config.learn_mode; i++) {
                                setpin(PIN_LED, 1);
+                               snd_on();
                                _delay_ms(10);
-                               //if (output_on || (config.learn_mode && learn_mode_off))
-                               //      goto drive_start;
                                setpin(PIN_LED, 0);
+                               snd_off();
+                               if (drive_on) goto drive_start;
                                _delay_ms(135);
-                               //if (output_on || (config.learn_mode && learn_mode_off))
-                               //      goto drive_start;
-
-                               //if (output_on || (config.learn_mode && learn_mode_off))
-                               //      goto drive_start;
+                               if (drive_on) goto drive_start;
                        }
                        for (i = 0; i < 15 - config.learn_mode; i++) {
-                               //if (output_on || (config.learn_mode && learn_mode_off))
-                               //      goto drive_start;
-                               setpin(PIN_LED, 0);
+                               if (drive_on) goto drive_start;
                                _delay_ms(70);
-                               //if (output_on || (config.learn_mode && learn_mode_off))
-                               //      goto drive_start;
-                               // _delay_ms(40);
                        }
                }
        }
        return 0;
 }
 
-
 /******************************************************************************
  *                        The end :-)
  */