*
*/
#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;
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
}
#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;
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;
(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);
}
"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
);
#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;
/*
* 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();
}