trennfix/sw: Timer based solution seems to work now.
authorPhilipp Hachtmann <hachti@hachti.de>
Sun, 26 Feb 2017 00:00:38 +0000 (01:00 +0100)
committerPhilipp Hachtmann <hachti@hachti.de>
Tue, 18 Apr 2023 20:03:20 +0000 (22:03 +0200)
Signed-off-by: Philipp Hachtmann <hachti@hachti.de>
trennfix/sw/config/trennfix_0.4.h
trennfix/sw/mk/trennfix_0.4.mk
trennfix/sw/mm/include/mm/mm_switch.h
trennfix/sw/mm/src/mm_switch.c

index b3b6b254f6f495bfd4b4bb7975fd9dc7de309aa0..dbce67fb740ba9d30d922ca3ecd6fa4fc8f476b1 100644 (file)
@@ -81,7 +81,7 @@ static inline void __attribute__((unused)) trigger_off(void)
 /*
  * Configuration for mm receiver code.
  */
-#define MM_SENSE (!PINVAL(PIN_SENSE))
+#define MM_SENSE (PINVAL(PIN_SENSE))
 #define MM_TIMER_INT_VECT TIMER0_OVF_vect
 
 #define MM_TSTART {                                                    \
index b4a097cb18cbf056305fcbe285097a04fc71af2e..b3558ce4967560773b804e66eba5e6cbcc3bf768 100644 (file)
@@ -24,7 +24,6 @@ endif
 LFUSE=0x61
 EFUSE=0xff
 
-#CFLAGS+= -DMM_FILTER_REPEATED
 CFLAGS+= -DUSE_REGISTER_VARS
 CFLAGS+= -DMM_USE_REGISTER_VARS
 CFLAGS+= -DWITH_EEPROM_UPDATE
index 561a1129afc091466a131c50bb7672f546aaca7d..240bea9b886a21f71d79077c27f1eac6cf5e6825 100644 (file)
@@ -14,7 +14,6 @@ uint8_t register shift_function asm("r3");
 uint8_t register shift_address asm("r4");
 uint8_t register mm_polarity asm("r5");
 uint8_t register mm_bitno asm("r6");
-uint8_t register mm_last_was_short asm("r8");
 uint8_t register mm_time_h asm("r9");
 uint8_t register mm_time_l asm("r10");
 uint8_t register mm_bit_val asm("r11");
@@ -26,7 +25,6 @@ static void inline __attribute((unused)) mm_init(void)
        mm_time_h = 0;
        mm_bit_val = 23;
        mm_polarity = 1;
-       mm_last_was_short = 0;
 }
 
 #else
index 937cd23571eb4f187dbcecde18831c9edf30f088..35016fcd4769d6826847d12ef697b992bdfcd7e0 100644 (file)
  *
  */
 #if !defined(MM_TSTART) || !defined(MM_SENSE) || !defined(MM_TIMER_INT_VECT)
-
 #error Missing needed MM_... macro!
-
 #endif
 
 /*
  *    Private global variables
  */
 
+enum recmode {
+       INIT,
+       ARMED,
+       MM_SLOW,
+       MM_FAST,
+       DCC,
+};
+enum recmode recmode = INIT;
+
 #ifndef MM_USE_REGISTER_VARS
 
 static volatile uint8_t mm_bitno = 0;
@@ -63,7 +70,6 @@ uint8_t mm_time_l = 0;
 uint8_t mm_bit_val = 23;
 static uint8_t mm_flavor;
 static uint8_t mm_polarity = 1;
-static uint8_t mm_last_was_short = 0;
 
 #endif
 
@@ -230,7 +236,7 @@ void shift(uint8_t value)
 }
 #endif
 
-static void mm_feed_bit(uint8_t bit, uint8_t seen_style)
+static void mm_feed_bit(uint8_t bit)
 {
        static volatile uint8_t shift_command_first;
        static volatile uint8_t shift_function_first;
@@ -238,16 +244,9 @@ static void mm_feed_bit(uint8_t bit, uint8_t seen_style)
        uint8_t address;
        uint8_t command;
 
-       if (mm_bitno == 0)
-               mm_flavor = seen_style;
-       else
-               if (seen_style != mm_flavor) {
-                       mm_bitno = 0;
-                       return;
-               }
-                       
        shift(bit);
        mm_bitno++;
+
        if (mm_bitno == 18) { /* Save first received word */
                shift_address_first  = shift_address;
                shift_function_first = shift_function;
@@ -260,11 +259,12 @@ static void mm_feed_bit(uint8_t bit, uint8_t seen_style)
                    (shift_address == shift_address_first) &&
                    (shift_function == shift_function_first)) {
                        address = lookup_decoder(shift_address);
-                       if (mm_flavor == MM_FLAVOR_DRIVE) {
+                       if (recmode == MM_SLOW) {
+                               trigger();
+
                                mm_switch_drive(address, shift_function,
                                                shift_command);
                        } else {
-                               trigger();
                                command = lookup_command(shift_command);
                                mm_switch_command(address, command);
                        }                               
@@ -286,10 +286,16 @@ void __attribute__((naked)) MM_TIMER_INT_VECT(void)
            "in r0, __SREG__    \n\t"
 #ifdef MM_USE_REGISTER_VARS
            "inc %[th]          \n\t"
+           "brne nover         \n\t"
+           "dec  %[th]         \n\t"
+           "nover:             \n\t"
 #else
            "push r1            \n\t"
-           "lds r1, mm_time_h     \n\t"
+           "lds r1, mm_time_h  \n\t"
            "inc r1             \n\t"
+           "brne nover         \n\t"
+           "dec r1             \n\t"
+           "nover:             \n\t"
            "sts  mm_time_h, r1    \n\t"
            "pop r1             \n\t"
 #endif
@@ -325,22 +331,20 @@ void __attribute__((naked)) PCINT0_vect(void)
            );
 #endif
 }
-
+       
 /* Pin change interrupt vector, here we have a bit more time */
 ISR(__vector_pinchange){
+       uint16_t duration;
+
        /* First kill off that timer */
        MM_TSTART;  /* Restart timer */
        
        /* Account for not yet handled timer overflow */
-       if (TIFR & _BV(TOV0)) {
-               mm_time_h++;
-               TIFR |= _BV(TOV0);
-       }
-       
-       mm_bit_val = !MM_SENSE;
+       TIFR |= _BV(TOV0);
 
-       uint16_t duration = mm_time_h << 8;
+       duration = mm_time_h << 8;
        duration += mm_time_l;
+       mm_bit_val = MM_SENSE;
        mm_time_h = 0;
 
        /*
@@ -354,39 +358,105 @@ ISR(__vector_pinchange){
         * Reality seems to look not as that exact. I measure
         * 26us for the clock pulse, but 196 for the long pulse.
         *
+        * Keep in mind: Time is counted in 500ns steps.
+        *
         */
-
 #define D_MATCH(d, v) ((duration > (d * 2 - 2 * v)) && (duration < (d * 2 + 2 * v)))
 
-       if (D_MATCH(26, 4)) {
-               if (mm_last_was_short)
-                       mm_polarity = mm_bit_val;
-               mm_last_was_short = 1;
-
-               if (mm_bit_val == mm_polarity)
-                       mm_feed_bit(0, MM_FLAVOR_DRIVE);
-       } else {
-               mm_last_was_short = 0;
-       }
-
-       if (mm_flavor == MM_FLAVOR_DRIVE) {
-               if (duration > 4096) { /* Maerklin inter package timeout 2ms */
-                       mm_bitno = 0;
-                       goto done;
+       switch(recmode) {
+       case INIT:
+       default:
+               break;
+       case ARMED:
+               /* Maerklin only interested when signal is 1 */
+               if (mm_bit_val == mm_polarity) {
+                       /* Fast short MM pulse (logical 0) */
+                       if (D_MATCH(13, 4)){
+                               recmode = MM_FAST;
+                               mm_feed_bit(0);
+                               goto done;
+                       }
+                       
+                       /* Slow short MM pulse (logical 0) */
+                       if (D_MATCH(26, 4)) {
+                               recmode = MM_SLOW;
+                               mm_feed_bit(0);
+                               goto done;
+                       }
+
+                       /* Fast long MM pulse (logical 1) */
+                       if (D_MATCH(91, 17)) {
+                               recmode = MM_FAST;
+                               mm_feed_bit(1);
+                               goto done;
+                       }
+
+                       /* Slow long MM pulse (logical 1) */
+                       if (D_MATCH(182, 25)) {
+                               recmode = MM_SLOW;
+                               mm_feed_bit(1);
+                               goto done;
+                       }
+               } 
+               break;
+
+       case MM_FAST:
+               if (mm_bit_val == mm_polarity) {
+
+                       /* Fast short MM pulse (logical 0) */
+                       if (D_MATCH(13, 4)){
+                               mm_feed_bit(0);
+                               goto done;
+                       }
+                       /* Fast long MM pulse (logical 1) */
+                       if (D_MATCH(91, 17)) {
+                               mm_feed_bit(1);
+                               goto done;
+                       }
+               } else {
+                       if (D_MATCH(13, 4))
+                               goto done;
+                       if (D_MATCH(91, 17))
+                               goto done;
+                       
+                       if (D_MATCH(700, 200))
+                               goto done;
                }
-       } else {
-               if (duration > 2000) { /* Maerklin inter package timeout 1ms */
-                       mm_bitno = 0;
-                       goto done;
+               break;
+                       
+       case MM_SLOW:
+               if (mm_bit_val == mm_polarity) {
+                       /* Slow short MM pulse (logical 0) */
+                       if (D_MATCH(26, 4)) {
+                               mm_feed_bit(0);
+                               goto done;
+                       }
+                       /* Slow long MM pulse (logical 1) */
+                       if (D_MATCH(182, 40)) {
+                               mm_feed_bit(1);
+                               goto done;
+                       }
+               } else {
+                       if (D_MATCH(26, 4))
+                               goto done;
+                       if (D_MATCH(182, 40))
+                               goto done;
+                       
+                       /* Accepted inter package gap */
+                       if (D_MATCH(1400, 400))
+                               goto done;
                }
+               break;
        }
-       
-       if (mm_bit_val != mm_polarity)
-               goto done;
 
-       if (D_MATCH(182, 25)) mm_feed_bit(1, MM_FLAVOR_DRIVE);
-       if (D_MATCH(91, 17))  mm_feed_bit(1, MM_FLAVOR_SWITCH);
-       if (D_MATCH(13, 4))   mm_feed_bit(0, MM_FLAVOR_SWITCH);
+       /* 
+        * If we have reached here, our pulse comes in somehow unexpected.
+        * We kill of everything by re-arming the state machine.
+        */
+       /* Start over receiver */
+       mm_bitno = 0;
+       mm_polarity = !mm_bit_val;
+       recmode = ARMED;
  done:
        mm_switch_pinchange_callback();
  }