trennfix/sw: Added smokefix, further modularized the mm decoder
[eisenbahn.git] / trennfix / sw / src / main.c
diff --git a/trennfix/sw/src/main.c b/trennfix/sw/src/main.c
deleted file mode 100644 (file)
index 3e7d265..0000000
+++ /dev/null
@@ -1,514 +0,0 @@
-/******************************************************************************
- *
- *  Trennfix firmware - main.c
- *
- *  Copyright (C) 2017 Philipp Hachtmann
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- *****************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <avr/io.h>
-#include <avr/eeprom.h>
-#include <avr/interrupt.h>
-#include <avr/pgmspace.h>
-
-#include <util/delay.h>
-#include <stdint.h>
-#include <mm/mm_switch.h>
-#include <config/hardware.h>
-
-#define EE_MAGIC 0xab
-
-enum op_mode {
-       OM_MOMENTARY,     /* on as long as "key on" pressed   */
-       OM_DOUBLE,        /* On off with "on" and "off" keys  */
-       OM_TOGGLE,        /* toggle on "key on" pressed       */
-       OM_ERASED = 0xff  /* EEPROM erased, need setup        */
-};
-
-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_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 {
-       uint8_t magic; /* Magic value */
-       enum op_mode op_mode;
-       uint8_t decoder_on;
-       uint8_t key_on;
-       uint8_t decoder_off;
-       uint8_t key_off;
-       uint8_t initial_pulse; /* Lenghth of initial pulse in 10ms steps   */
-       uint8_t on_duty_cycle; /* Duty cycle for on. 0-10                  */
-        volatile enum learn_mode  learn_mode;
-};
-
-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;
-       c = (divisor * 2) / 3;
-       OCR1B = c;
-       for (c = 0; c < duration - pause; c++)
-               _delay_ms(2);
-       TCCR1 = 0x6;
-       OCR1C = PWM_CYCLE;
-       OCR1B = 12;
-       for (c = 0; c < pause; c++)
-               _delay_ms(2);
-       TCCR1 = 0x6;
-       OCR1C = PWM_CYCLE;
-       OCR1B = PWM_CYCLE;
-}
-
-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 = PWM_CYCLE;
-       OCR1B = PWM_CYCLE;
-}
-
-#else
-#define play_tone(...)
-#define tone_enter(...)
-#define tone_good(...)
-#define snd_on(...)
-#define snd_off(...)
-#endif
-
-static void load_config(void)
-{
-       eeprom_read_block((uint8_t *)&config, &ee_config, sizeof(config));
-}
-
-static void save_config(void)
-{
-#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
-}
-
-void mm_switch_pinchange_callback(void)
-{
-       static uint8_t btn_last = 0;
-
-       if (BTN_PRESSED && !btn_last) {
-               config.learn_mode++;
-               config.learn_mode %= LM_END;
-       }
-       btn_last = BTN_PRESSED;
-}
-
-static uint8_t get_speed(uint8_t command)
-{
-       uint8_t b1, b3, b5, b7;
-               
-       b1 = ((command & 0x80) != 0);
-       b3 = ((command & 0x20) != 0);
-       b5 = ((command & 0x8) != 0);
-       b7 = ((command & 0x2) != 0);
-       
-       //if ((b1 != b2) || (b2 != b3) || (b3 != b4) || (b5 != b6) || (b7 != b8))
-       //      return 0xff;
-       return (b1 + b3 * 2 + b5 * 4 +b7 * 8);
-}
-
-
-void mm_switch_drive(uint8_t loco, uint8_t function, uint8_t command)
-{
-       uint8_t speed;
-       speed = get_speed(command);
-       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();
-                       }
-                       break;
-
-               case LM_EASY_WAIT_PRESS:
-                       if (speed != 1)
-                           config.learn_mode = LM_OFF;
-                       break;
-
-               default:
-                       break;
-               }
-               alert_last = (speed == 1);
-               break;
-
-       case 50:
-               if (speed)
-                       speed = speed - 1;
-
-               if (config.learn_mode == LM_EASY_MODE) {
-                       config.initial_pulse = speed;
-               }
-               break;
-       case 51:
-               if (speed)
-                       speed = speed - 1;
-
-               if (config.learn_mode == LM_EASY_MODE)
-                       config.on_duty_cycle = speed;
-               break;
-       }
-       
-}
-
-void mm_switch_command(uint8_t decoder, uint8_t command)
-{
-       static uint8_t toggle_lock = 0;
-
-       switch(config.learn_mode) {
-
-       case LM_OFF:
-       default:
-               if ((decoder == config.decoder_on) &&
-                   (command == config.key_on)) { /* Primary key pressed */
-                       switch(config.op_mode) {
-                       case OM_MOMENTARY:
-                       case OM_DOUBLE:
-                               drive_on = 1;
-                               break;
-                       case OM_TOGGLE:
-                               if (!toggle_lock) {
-                                       drive_on = ~drive_on;
-                                       toggle_lock = 1;
-                               }
-                               break;
-                       default:
-                               break;
-                       }
-               }
-               if ((decoder == config.decoder_on) &&
-                   (command == 0)) {  /* Primary key released */
-                       switch(config.op_mode) {
-                       case OM_MOMENTARY:
-                               drive_on = 0;
-                               break;
-                       case OM_TOGGLE:
-                               toggle_lock = 0;
-                               break;
-                       default:
-                               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) &&
-                   (command == config.key_off)) { /* Secondary "off" key pressed */
-                       switch(config.op_mode) {
-                       case OM_DOUBLE:
-                               drive_on = 0;
-                               break;
-                       case OM_TOGGLE:
-                       case OM_MOMENTARY:
-                       default:
-                               break;
-                       }
-               }
-#endif
-               break;
-               
-       case LM_LEARN_ON_KEY:
-               if (command) {
-                       config.decoder_on = decoder;
-                       config.key_on     = command;
-                       if (config.op_mode == OM_DOUBLE)
-                               config.learn_mode = LM_LEARN_OFF_KEY;
-                       else
-                               config.learn_mode = LM_OFF;
-                       save_config();
-               }
-               break;
-#ifdef LEARN_ADVANCED
-       case LM_LEARN_OFF_KEY:
-               if (command) {
-                       config.decoder_off = decoder;
-                       config.key_off     = command;
-                       config.learn_mode = LM_OFF;
-                       save_config();
-               }
-               break;
-               
-       case LM_LEARN_INITIAL:
-               if (drive_on) {
-                       if (command == 0)
-                               drive_on = 0;
-                       
-               } else {
-                       switch(command) {
-                       case 1:
-                               if (config.initial_pulse >= 10)
-                                       config.initial_pulse -= 10;
-                               else 
-                                       config.initial_pulse = 0;
-                               save_config();
-                               drive_on = 1;
-                               break;
-                       case 2:
-                               if (config.initial_pulse <= 245)
-                                       config.initial_pulse += 10;
-                               else
-                                       config.initial_pulse = 255;
-                               save_config();
-                               drive_on = 1;
-                               break;
-                       default:
-                               break;
-                       }
-               }
-               break;
-
-       case LM_LEARN_DUTY:
-               if (drive_on) {
-                       if (command == 0)
-                               drive_on = 0;
-               } else {
-                       switch(command) {
-                       case 1:
-                               if (config.on_duty_cycle > 0)
-                                       config.on_duty_cycle -= 1;
-                               save_config();
-                               drive_on = 1;
-                               break;
-                       case 2:
-                               if (config.on_duty_cycle < 10)
-                                       config.on_duty_cycle += 1;
-                               save_config();
-                               drive_on = 1;
-                               break;
-                       default:
-                               break;
-                       }
-               }
-               break;
-               
-       case LM_LEARN_OP_MODE:
-               switch(command) {
-               case 1:
-                       config.op_mode = OM_MOMENTARY;
-                       save_config();
-                       config.learn_mode = LM_OFF;
-                       break;
-               case 3:
-                       config.op_mode = OM_DOUBLE;
-                       save_config();
-                       config.learn_mode = LM_OFF;
-                       break;
-               case 5:
-                       config.op_mode = OM_TOGGLE;
-                       save_config();
-                       config.learn_mode = LM_OFF;
-                       break;
-               default:
-                       break;
-               }
-               break;
-#endif
-       }
-}
-
-
-/******************************************************************************
- *
- * main() - The main routine
- *
- */
-void shift(uint8_t mu);
-
-#ifdef WITH_PWM
-#define DRIVE_OFF  {OCR1B = PWM_CYCLE;}
-#define DRIVE_ON   {OCR1B = PWM_CYCLE - config.on_duty_cycle;}
-#define DRIVE_FULL {OCR1B = 0;}
-#else
-#define DRIVE_OFF  {setpin(PIN_DRIVE, 0); setpin(PIN_LED, 0);}
-#define DRIVE_ON   {setpin(PIN_DRIVE, 1); setpin(PIN_LED, 1);}
-#define DRIVE_FULL {setpin(PIN_DRIVE, 1); setpin(PIN_LED, 1);}
-#endif
-
-int main(void) {
-       uint16_t i;
-
-#ifdef WITH_INITIAL_PULSE
-       uint8_t drive_last = 0;
-       uint8_t drive_slope = 0;
-#endif
-
-#ifdef USE_REGISTER_VARS
-       drive_on = 0;
-#endif
-       mm_init();
-       load_config();
-       setup_hw();
-
-       if (config.magic != EE_MAGIC) {
-               config.magic = EE_MAGIC;
-               config.op_mode = OM_MOMENTARY;
-               config.decoder_on = 1;
-               config.key_on = 1;
-               config.decoder_off = 1;
-               config.key_off = 2;
-               config.initial_pulse = 10;
-               config.on_duty_cycle = 5;
-               config.learn_mode = LM_LEARN_ON_KEY;
-       }
-       sei();
-       while (1) {
-       drive_start:
-
-#ifdef WITH_INITIAL_PULSE
-               cli();
-               if (drive_on && !drive_last)
-                       drive_slope = 1;
-               else
-                       drive_slope = 0;
-               drive_last = drive_on;
-               sei();
-#endif
-               if (drive_on) {
-
-#ifdef WITH_INITIAL_PULSE
-                       if (drive_slope) {
-                               DRIVE_FULL;
-                               for (i = 0; i < config.initial_pulse; i++) {
-                                       _delay_ms(5);
-                               }
-                       }
-#endif
-                       DRIVE_ON;
-               
-               } else {
-                       DRIVE_OFF;
-
-                       if (!config.learn_mode ||
-                           config.learn_mode > LM_LEARN_OP_MODE)
-                               continue;
-
-                       for (i = 0; i < config.learn_mode; i++) {
-                               setpin(PIN_LED, 1);
-                               snd_on();
-                               _delay_ms(10);
-                               setpin(PIN_LED, 0);
-                               snd_off();
-                               if (drive_on) goto drive_start;
-                               _delay_ms(135);
-                               if (drive_on) goto drive_start;
-                       }
-                       for (i = 0; i < 15 - config.learn_mode; i++) {
-                               if (drive_on) goto drive_start;
-                               _delay_ms(70);
-                       }
-               }
-       }
-       return 0;
-}
-
-/******************************************************************************
- *                        The end :-)
- */