trennfix/sw: Temporary
[eisenbahn.git] / trennfix / sw / mm_switch.c
index 74939bf48f84d92b21f96d1ec1424e70653ea250..cb7b4f7656d32dea6c63a30e3647c698cc772b5a 100644 (file)
@@ -36,7 +36,7 @@
 #include "hardware.h"
 #include "mm_switch.h"
 
- #define DEBUG_TIMEOUT
+// #define DEBUG_TIMEOUT
 #ifdef DEBUG_TIMEOUT
 #define MON(val) setpin(PIN_DRIVE, val)
 #else
  * Lookup decoder number.
  *
  */
+
+static uint8_t lookup_nibble(uint8_t mm_nibble)
+{
+       switch(mm_nibble) {
+       case 0x0: return 0;
+       case 0xc: return 1;
+       case 0x8: return 2;
+       case 0x3: return 3;
+       case 0xf: return 4;
+       case 0xb: return 5;
+       case 0x2: return 6;
+       case 0xe: return 7;
+       case 0xa: return 8;
+       default: return 0;
+       }
+       return 0;
+}
+
 static uint8_t lookup_decoder(uint8_t mm_byte)
 {
-       switch(mm_byte) {
-               /* 0x00 is invalid */
-       case 0xc0: return 1;
-       case 0x80: return 2;
-        case 0x30: return 3;
-        case 0xf0: return 4;
-        case 0xb0: return 5;
-        case 0x20: return 6;
-        case 0xe0: return 7;
-        case 0xa0: return 8;
-
-        case 0x0c: return 9;
-       case 0xcc: return 10;
-       case 0x8c: return 11;
-        case 0x3c: return 12;
-        case 0xfc: return 13;
-        case 0xbc: return 14;
-        case 0x2c: return 15;
-        case 0xec: return 16;
-        case 0xac: return 17;
-
-        case 0x08: return 18;
-       case 0xc8: return 19;
-       case 0x88: return 20;
-        case 0x38: return 21;
-        case 0xf8: return 22;
-        case 0xb8: return 23;
-        case 0x28: return 24;
-        case 0xe8: return 25;
-       
-       default:
+       uint8_t low;
+       uint8_t high;
+       if (mm_byte == 0)
+               return 100;
+       low = lookup_nibble(mm_byte >> 4);
+       high = lookup_nibble(mm_byte & 0xf);
+       if (!low)
                return 0;
-       }
+       return 9 * high + low;
 }
 
 static uint8_t lookup_command(uint8_t mm_byte)
@@ -101,7 +95,8 @@ static uint8_t lookup_command(uint8_t mm_byte)
         }
 }
 
-static void mm_switch_init(void)
+
+static __attribute__((unused)) void mm_switch_init(void)
 {
        /* Get rid of the 1/8 clock prescaler */
        CLKPR = (1 << CLKPCE);
@@ -124,27 +119,27 @@ static void mm_switch_init(void)
        TIMSK |= _BV(TOIE1); /* Overflow interrupt */
 }
 
-
-static volatile uint8_t shift_sub;
-static volatile uint8_t shift_zero;
-static volatile uint8_t shift_decoder;
-static volatile uint8_t shift_sub_first;
-static volatile uint8_t shift_decoder_first;
+static volatile uint8_t shift_command;
+static volatile uint8_t shift_function;
+static volatile uint8_t shift_address;
+static volatile uint8_t shift_command_first;
+static volatile uint8_t shift_address_first;
 
 /* We will shift from right to left.
  * XXXXXXXX        XX          XXXXXXXX
- * shift_decoder   shift_zero  shift_sub
+ * shift_address   shift_function  shift_command
  *
- * The bits 7 downto 2 of shift_zero are ignored.
+ * The bits 7 downto 2 of shift_function are ignored.
  */
 
 volatile uint8_t bitno = 0;
 
-static void trigger(void)
+static void __attribute__((unused)) trigger(void)
 {
        setpin(PIN_DRIVE, 1);
-       _delay_us(10);
+       _delay_us(4);
        setpin(PIN_DRIVE, 0);
+       _delay_us(4);
 }
 
 enum recstate {
@@ -161,21 +156,23 @@ static enum recstate recstate = IDLE;
 
 static inline void shift(uint8_t value)
 {
-       shift_decoder <<= 1;
-       if (shift_zero & 2)
-               shift_decoder |= 1;
-       shift_zero <<= 1;
-       if (shift_sub & 0x80)
-               shift_zero |= 1;
-       shift_sub <<= 1;
+       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_sub |= 1;
+               shift_command |= 1;
 }
 
 
 ISR(TIMER0_COMPA_vect) {
-
        static uint8_t patience = 0;
+       static uint8_t address_last = 0xff;
+       static uint8_t function_last = 0xff;
+       static uint8_t command_last = 0xff;
 
        switch(recstate) {
        case FIRST_FAST_SAMPLE:
@@ -212,6 +209,7 @@ ISR(TIMER0_COMPA_vect) {
                        TSTART_CLK_TO_SAMPLE_SLOW;
                        return;
                }
+       default:
                TSTOP;
                recstate = IDLE;
                return;
@@ -219,31 +217,43 @@ ISR(TIMER0_COMPA_vect) {
        
        shift(MM_SENSE);
        bitno++;
-       
+
        if (bitno == 18) { /* Save first received word */
-               shift_sub_first = shift_sub;
-               shift_decoder_first = shift_decoder;
+               shift_command_first = shift_command;
+               shift_address_first = shift_address;
                patience = 18;
 
        } 
+
        if (bitno == 36) {
-               if ((shift_sub == shift_sub_first) &&
-                   (shift_decoder == shift_decoder_first)) {
-                       uint8_t decoder = lookup_decoder(shift_decoder);
-                       uint8_t command = lookup_command(shift_sub);
-                       if (recstate == SLOW_WAIT_FOR_CLOCK)
-                               trigger();
-                       if (decoder) {
-                               /* Congratulations, we have a valid command */
-                               if (recstate == FAST_WAIT_FOR_CLOCK) {
-                                       //      trigger();
-                                       mm_switch_command(decoder, command);
+               if ((shift_command == shift_command_first) &&
+                   (shift_address == shift_address_first)) {
+                       if ((shift_address != address_last) || (shift_command != command_last) ||
+                           shift_function != function_last) {
+
+                               uint8_t addr =  lookup_decoder(shift_address);
+                               
+                               if (recstate == SLOW_WAIT_FOR_CLOCK) {
+                                       mm_switch_drive(addr, shift_function, shift_command);
+                               }
+                       
+               
+                               if (recstate == FAST_WAIT_FOR_CLOCK && addr) {
+                                       uint8_t command = lookup_command(shift_command);
+                                       /* Congratulations, we have a valid command */
+                                       mm_switch_command(addr, command);
                                }
                        }
+                       address_last = shift_address;
+                       function_last = shift_function;
+                       command_last = shift_command;
                }
+               
        }
 }
 
+//void __attribute((weak)) mm_switch_drive(uint8_t address, uint8_t function, uint8_t command);
+
 ISR(BADISR_vect)
 {
        while(1) {
@@ -264,7 +274,7 @@ ISR(TIM0_OVF_vect)
 {
        return;
        while(1) {
-               setpin(PIN_LED, 1);
+               setpin(PIN_LED, 1);
                _delay_ms(30);
                setpin(PIN_LED, 0);
                _delay_ms(300);
@@ -283,7 +293,7 @@ void mm_pinchange_handler(void)
        sense_last = MM_SENSE;
        if (!sense_last)
                return;
-       
+
        switch(recstate) {
        case IDLE:
                bitno = 0;