trennfix/sw: Fixed a bit beauty.
[eisenbahn.git] / trennfix / sw / mm / src / mm_switch.c
index 34819e5d626071098f1d6ca1660163799f15eb0d..937cd23571eb4f187dbcecde18831c9edf30f088 100644 (file)
 
 #ifndef MM_USE_REGISTER_VARS
 
-static volatile uint8_t bitno = 0;
+static volatile uint8_t mm_bitno = 0;
 static uint8_t shift_command;
 static uint8_t shift_function;
 static uint8_t shift_address;
-static  enum mm_recstate recstate = MM_IDLE;
-static uint8_t sense_last = 23;
-uint8_t time_h = 0;
-uint8_t time_l = 0;
-uint8_t bit_val = 23;
+uint8_t mm_time_h = 0;
+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
 
@@ -90,13 +91,20 @@ static uint8_t __attribute__((unused)) lookup_decoder(uint8_t mm_byte)
 {
        uint8_t low;
        uint8_t high;
+       uint8_t retval;
+
        if (mm_byte == 0)
                return 80;
        low = lookup_nibble(mm_byte >> 4);
        high = lookup_nibble(mm_byte & 0xf);
        if (!low)
                return 0;
-       return 9 * high + low;
+
+       /*      retval = 9 * high + low; */
+       retval = high << 3;
+       retval += high;
+       retval += low;
+       return retval;
 }
 
 static uint8_t __attribute__((unused)) lookup_command(uint8_t mm_command)
@@ -184,9 +192,26 @@ static uint8_t __attribute__((unused)) lookup_command(uint8_t mm_command)
  * shift_address   shift_function  shift_command
  *
  * The bits 7 downto 2 of shift_function are ignored.
+ *
+ * First comes the C implementation of the shift routine.
+ * It is usually not used anymore, but I left it for
+ * illustration purposes.
+ * The real shift function is written in assembly and saves many instructions.
  */
-#define SAVE_ANOTHER_40_BYTES
-#ifdef SAVE_ANOTHER_40_BYTES
+#if 0
+void shift(uint8_t value)
+{
+       shift_address <<= 1;
+       if (shift_function & 2)
+               shift_address |= 1;
+       shift_function <<= 1;
+       if (shift_command & 0x80)
+               shift_function |= 1;
+       shift_command <<= 1;
+       if (value)
+               shift_command |= 1;
+}
+#else
 
 void shift(uint8_t value)
 {
@@ -203,31 +228,9 @@ void shift(uint8_t value)
            "2" (shift_address), [val] "r" (value)
            );
 }
-
-#else /* This is what we do to shift */
-
-void shift(uint8_t value)
-{
-       shift_address <<= 1;
-       if (shift_function & 2)
-               shift_address |= 1;
-       shift_function <<= 1;
-       if (shift_command & 0x80)
-               shift_function |= 1;
-       shift_command <<= 1;
-       if (value)
-               shift_command |= 1;
-}
 #endif
 
-static volatile uint8_t mm_rec_tolerated_timeouts;
-
-#define MM_SLOW 0
-#define MM_FAST 1
-
-static uint8_t style;
-
-void mm_feed_bit(uint8_t bit, uint8_t seen_style)
+static void mm_feed_bit(uint8_t bit, uint8_t seen_style)
 {
        static volatile uint8_t shift_command_first;
        static volatile uint8_t shift_function_first;
@@ -235,68 +238,44 @@ void mm_feed_bit(uint8_t bit, uint8_t seen_style)
        uint8_t address;
        uint8_t command;
 
-#ifdef MM_FILTER_REPEATED
-       static uint8_t address_last = 0xff;
-       static uint8_t function_last = 0xff;
-       static uint8_t command_last = 0xff;
-#endif
-
-       if (bitno == 0)
-               style = seen_style;
+       if (mm_bitno == 0)
+               mm_flavor = seen_style;
        else
-               if (seen_style != style) {
-                       bitno = 0;
+               if (seen_style != mm_flavor) {
+                       mm_bitno = 0;
                        return;
                }
                        
        shift(bit);
-       bitno++;
-       if (bitno == 18) { /* Save first received word */
+       mm_bitno++;
+       if (mm_bitno == 18) { /* Save first received word */
                shift_address_first  = shift_address;
                shift_function_first = shift_function;
                shift_command_first  = shift_command;
-               mm_rec_tolerated_timeouts = 18;
        } 
 
-       if (bitno == 36) {
+       if (mm_bitno == 36) {
 
                if ((shift_command == shift_command_first) &&
                    (shift_address == shift_address_first) &&
                    (shift_function == shift_function_first)) {
-                       
-
-#ifdef MM_FILTER_REPEATED
-                       if ((shift_address != address_last) || (shift_command != command_last) ||
-                           shift_function != function_last) {
-#endif
-                               if (style == MM_SLOW) {
-                                       address = lookup_decoder(shift_address);
-                                       mm_switch_drive(address, shift_function, shift_command);
-                               } else {
-                                       trigger();
-
-                                       command = lookup_command(shift_command);
-                                       mm_switch_command(address, command);
-                               }                               
-                               bitno = 0;
-#ifdef MM_FILTER_REPEATED
-                       }
-                       address_last   = shift_address;
-                       function_last  = shift_function;
-                       command_last   = shift_command;
-#endif
+                       address = lookup_decoder(shift_address);
+                       if (mm_flavor == MM_FLAVOR_DRIVE) {
+                               mm_switch_drive(address, shift_function,
+                                               shift_command);
+                       } else {
+                               trigger();
+                               command = lookup_command(shift_command);
+                               mm_switch_command(address, command);
+                       }                               
                }
                
        }
 }
 
-ISR(__vector_timer_extra) {
-       //trigger();
-}
-
 /*
  *  The timeout interrupt vector does nothing else
- *  than incrementing the time_h round counter.
+ *  than incrementing the mm_time_h round counter.
  *
  *  It is written in naked assembly because we want to avoid pushing
  *  and popping of all upper registers.
@@ -309,17 +288,16 @@ void __attribute__((naked)) MM_TIMER_INT_VECT(void)
            "inc %[th]          \n\t"
 #else
            "push r1            \n\t"
-           "lds r1, time_h     \n\t"
+           "lds r1, mm_time_h     \n\t"
            "inc r1             \n\t"
-           "sts  time_h, r1    \n\t"
+           "sts  mm_time_h, r1    \n\t"
            "pop r1             \n\t"
 #endif
            "out __SREG__, r0    \n\t"
            "pop r0              \n\t"
-           //      "rjmp __vector_timer_extra \n\t"
            "reti                \n\t"
 #ifdef MM_USE_REGISTER_VARS
-           :: [th] "r" (time_h)
+           :: [th] "r" (mm_time_h)
 #endif
            );
 }
@@ -335,12 +313,12 @@ void __attribute__((naked)) PCINT0_vect(void)
 #ifdef MM_USE_REGISTER_VARS
        asm("in %[tl], %[tmr]   \n\t"
            "rjmp __vector_pinchange  \n\t"
-           :: [tl] "r" (time_l), [tmr] "I" (_SFR_IO_ADDR(TCNT0))
+           :: [tl] "r" (mm_time_l), [tmr] "I" (_SFR_IO_ADDR(TCNT0))
            );
 #else
        asm("push r0         \n\t"
            "in r0, %[tmr]   \n\t"
-           "sts time_l, r0  \n\t"
+           "sts mm_time_l, r0  \n\t"
            "pop r0          \n\t"
            "rjmp __vector_pinchange  \n\t"
            :: [tmr] "I" (_SFR_IO_ADDR(TCNT0))
@@ -351,20 +329,19 @@ void __attribute__((naked)) PCINT0_vect(void)
 /* Pin change interrupt vector, here we have a bit more time */
 ISR(__vector_pinchange){
        /* First kill off that timer */
-
        MM_TSTART;  /* Restart timer */
        
        /* Account for not yet handled timer overflow */
        if (TIFR & _BV(TOV0)) {
-               time_h++;
+               mm_time_h++;
                TIFR |= _BV(TOV0);
        }
        
-       bit_val = !MM_SENSE;
+       mm_bit_val = !MM_SENSE;
 
-       uint16_t duration = time_h << 8;
-       duration += time_l;
-       time_h = 0;
+       uint16_t duration = mm_time_h << 8;
+       duration += mm_time_l;
+       mm_time_h = 0;
 
        /*
         * The nominal length of a bit cycle is 208 us.
@@ -381,44 +358,40 @@ ISR(__vector_pinchange){
 
 #define D_MATCH(d, v) ((duration > (d * 2 - 2 * v)) && (duration < (d * 2 + 2 * v)))
 
-       static uint8_t mm_positive = 1;
-       static uint8_t last_was_short = 0;
-
        if (D_MATCH(26, 4)) {
-               if (last_was_short)
-                       mm_positive = bit_val;
-               last_was_short = 1;
+               if (mm_last_was_short)
+                       mm_polarity = mm_bit_val;
+               mm_last_was_short = 1;
 
-               if (bit_val == mm_positive)
-                       mm_feed_bit(0, MM_SLOW);
+               if (mm_bit_val == mm_polarity)
+                       mm_feed_bit(0, MM_FLAVOR_DRIVE);
        } else {
-               last_was_short = 0;
+               mm_last_was_short = 0;
        }
 
-       if (style == MM_SLOW) {
-               if (duration > 4000) { /* Maerklin inter package timeout 2ms */
-                       bitno = 0;
+       if (mm_flavor == MM_FLAVOR_DRIVE) {
+               if (duration > 4096) { /* Maerklin inter package timeout 2ms */
+                       mm_bitno = 0;
                        goto done;
                }
        } else {
                if (duration > 2000) { /* Maerklin inter package timeout 1ms */
-                       bitno = 0;
+                       mm_bitno = 0;
                        goto done;
                }
        }
        
-       if (bit_val != mm_positive)
+       if (mm_bit_val != mm_polarity)
                goto done;
 
-       if (D_MATCH(182, 25)) mm_feed_bit(1, MM_SLOW);
-       
-       if (D_MATCH(91, 17)) {mm_feed_bit(1, MM_FAST);}
-       if (D_MATCH(13, 4)) {mm_feed_bit(0, MM_FAST);}
-
+       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);
  done:
        mm_switch_pinchange_callback();
  }
 
+
 void __attribute__((weak))mm_switch_pinchange_callback(void)
 {
 }
@@ -433,7 +406,6 @@ void __attribute__((weak))mm_switch_command(uint8_t address, uint8_t command)
 }
 
 
-
 /******************************************************************************
  *                        The end :-)
  */