From c839c431361d81dd2ff5a2ac46401204a7bf019e Mon Sep 17 00:00:00 2001 From: Philipp Hachtmann Date: Sun, 26 Feb 2017 01:00:38 +0100 Subject: [PATCH] trennfix/sw: Timer based solution seems to work now. Signed-off-by: Philipp Hachtmann --- trennfix/sw/config/trennfix_0.4.h | 2 +- trennfix/sw/mk/trennfix_0.4.mk | 1 - trennfix/sw/mm/include/mm/mm_switch.h | 2 - trennfix/sw/mm/src/mm_switch.c | 168 ++++++++++++++++++-------- 4 files changed, 120 insertions(+), 53 deletions(-) diff --git a/trennfix/sw/config/trennfix_0.4.h b/trennfix/sw/config/trennfix_0.4.h index b3b6b25..dbce67f 100644 --- a/trennfix/sw/config/trennfix_0.4.h +++ b/trennfix/sw/config/trennfix_0.4.h @@ -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 { \ diff --git a/trennfix/sw/mk/trennfix_0.4.mk b/trennfix/sw/mk/trennfix_0.4.mk index b4a097c..b3558ce 100644 --- a/trennfix/sw/mk/trennfix_0.4.mk +++ b/trennfix/sw/mk/trennfix_0.4.mk @@ -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 diff --git a/trennfix/sw/mm/include/mm/mm_switch.h b/trennfix/sw/mm/include/mm/mm_switch.h index 561a112..240bea9 100644 --- a/trennfix/sw/mm/include/mm/mm_switch.h +++ b/trennfix/sw/mm/include/mm/mm_switch.h @@ -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 diff --git a/trennfix/sw/mm/src/mm_switch.c b/trennfix/sw/mm/src/mm_switch.c index 937cd23..35016fc 100644 --- a/trennfix/sw/mm/src/mm_switch.c +++ b/trennfix/sw/mm/src/mm_switch.c @@ -43,15 +43,22 @@ * */ #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(); } -- 2.32.0