From: Philipp Hachtmann Date: Mon, 6 Feb 2017 00:37:59 +0000 (+0100) Subject: trennfix/sw: Single timer version X-Git-Url: http://gitweb.hachti.de/?p=eisenbahn.git;a=commitdiff_plain;h=7009567750e2698fb4420e9ceb6ad8cc9659c7a3 trennfix/sw: Single timer version Single timer version. For debugging only. Signed-off-by: Philipp Hachtmann --- diff --git a/trennfix/sw/config.make b/trennfix/sw/config.make index 303a371..17f249d 100644 --- a/trennfix/sw/config.make +++ b/trennfix/sw/config.make @@ -1,5 +1,5 @@ -SRC = main.c +SRC = main.c mm_switch.c ################################################################################ ################################################################################ diff --git a/trennfix/sw/hardware.h b/trennfix/sw/hardware.h new file mode 100644 index 0000000..edcd7ff --- /dev/null +++ b/trennfix/sw/hardware.h @@ -0,0 +1,68 @@ +#ifndef __HARDWARE_H +#define __HARDWARE_H + + +#include "pin_magic.h" + +#define PIN_LED _PIN(PORTB, PORTB2) +#define PIN_SENSE _PIN(PORTB, PORTB4) +#define PIN_DRIVE _PIN(PORTB, PORTB3) +#define PIN_BTN _PIN(PORTB, PB1) + +#define MM_SENSE (!PINVAL(PIN_SENSE)) +#define BTN_PRESSED (!PINVAL(PIN_BTN)) + +#define START_TIMER0 ({TCNT0 = 0; TCCR0B = 2;}) +#define START_TIMER1 ({TCNT1 = 1; TCCR1 = 7; GTCCR |= 2;}) +#define STOP_TIMER1 ({TCCR1 = 0; TCNT1 = 1;}) + + +static inline void setup_hw(void) +{ + /* Turn off the 1/8 clock prescaler - now running at 16MHz*/ + CLKPR = (1 << CLKPCE); + CLKPR = 0; + + INPUT_PIN(PIN_SENSE); + INPUT_PIN(PIN_BTN); + OUTPUT_PIN(PIN_DRIVE); + OUTPUT_PIN(PIN_LED); + setpin(PIN_BTN, 1); /* Need pullup */ + + GIMSK |= _BV(PCIE); /* Enable pin change interrupt for sense port */ + PCMSK |= _BV(PCINT4); /* PB4, Rail sense input */ + + /* Change interrupt for button */ + PCMSK |= _BV(PCINT1); /* PB1 */ + + /* Setup timer 0, used for mm_switch */ + TCCR0A = 0; /* Normal mode */ + TCCR0B = 0; /* Timer off */ + TIMSK |= _BV(OCIE0A); /* Get a match interrupt */ + + /* We need 13 + 45,5 us delay, That's 464 clocks @8MHz*/ + //OCR0A = 91; /* Prescaler 8 is used */ + + /* Timer 1 for timeout */ + /* We set it to 1024us by prescaler 64 and running full 256 */ + // TCCR1 = 7; + // TIMSK |= _BV(TOIE1); /* Overflow interrupt */ +} + +/* deprecated */ +#define START_TIMER0 ({TCNT0 = 0; TCCR0B = 2;}) +#define START_TIMER1 ({TCNT1 = 1; TCCR1 = 7; GTCCR |= 2;}) +#define STOP_TIMER0 (TCCR0B = 0) +#define STOP_TIMER1 ({TCCR1 = 0; TCNT1 = 1;}) + +#define TSTART_CLK_TO_SAMPLE_FAST ({TCNT0 = 0; GTCCR |= 1; OCR0A = 110; TCCR0B = 2;}) +#define TSTART_CLK_TO_SAMPLE_SLOW ({TCNT0 = 0; GTCCR |= 1; OCR0A = 220; TCCR0B = 2;}) + +//#define TSTART_CLK_TO_SAMPLE_FAST ({TCNT0 = 0; GTCCR |= 1; OCR0A = 91; TCCR0B = 2;}) +//#define TSTART_CLK_TO_SAMPLE_SLOW ({TCNT0 = 0; GTCCR |= 1; OCR0A = 182; TCCR0B = 2;}) + +#define TSTOP ({TCCR0B = 0;}) + + + +#endif diff --git a/trennfix/sw/main.c b/trennfix/sw/main.c index d2111f7..4ae273a 100644 --- a/trennfix/sw/main.c +++ b/trennfix/sw/main.c @@ -31,16 +31,8 @@ #include #include -#include "pin_magic.h" -#include "mm_lookup.h" - -#define LED _PIN(PORTB, PORTB2) -#define SENSE _PIN(PORTB, PORTB4) -#define DRIVE _PIN(PORTB, PORTB3) -#define BTN _PIN(PORTB, PB1) - -#define SIGIN (!PINVAL(SENSE)) -#define BTN_PRESSED (!PINVAL(BTN)) +#include "mm_switch.h" +#include "hardware.h" // #define DEBUG_TIMEOUT #ifdef DEBUG_TIMEOUT @@ -49,187 +41,218 @@ #define MON_TIMEOUT(xx) ({0;}) #endif -uint8_t EEMEM ee_our_decoder; -uint8_t EEMEM ee_our_key; - -static void setup_hw(void) -{ - /* Get rid of the 1/8 clock prescaler */ - CLKPR = (1 << CLKPCE); - CLKPR = 0; - - INPUT_PIN(SENSE); - INPUT_PIN(BTN); - OUTPUT_PIN(DRIVE); - OUTPUT_PIN(LED); - setpin(BTN, 1); /* Need pullup */ - _delay_ms(1); /* Let the line rise */ - - - GIMSK |= _BV(PCIE); /* Enable pin change interrupt */ - PCMSK = _BV(PCINT4); /* PB4, Rail sense input */ - - TCCR0A = 0; /* This is normal mode */ - TCCR0B = 0; /* Timer off */ - TIMSK |= _BV(OCIE0A); /* Get a match interrupt */ - TIMSK |= _BV(TOV0); /* Overflow interrupt */ - - /* We need 13 + 45 us delay, That's 464 clocks @8MHz*/ - OCR0A = 91; /* Prescaler 8 is used */ - - /* Timer 1 for timeout */ - /* We set it to 1024us by prescaler 64 and running full 256 */ - TCCR1 = 7; - TIMSK |= _BV(TOIE1); /* Overflow interrupt */ -} - -static uint8_t ctr = 0; - -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; - -/* We will shift from right to left. - * XXXXXXXX XX XXXXXXXX - * shift_decoder shift_zero shift_sub - * - * The bits 7 downto 2 of shift_zero are ignored. - */ - -#define STOP_TIMER0 (TCCR0B = 0) - -volatile uint8_t bitno = 0; - - -static void zero(void) +#define EE_MAGIC 0xab + +enum op_mode { + OM_MOMENTARY, /* on as long as "key on" pressed */ + OM_DOUBLE, /* On off with "on" and "off" keys */ + OM_TOGGLE, /* toggle on "key on" pressed */ + OM_ERASED = 0xff /* EEPROM erased, need setup */ +}; + +enum learn_mode { + LM_OFF = 0, + LM_LEARN_ON_KEY, /* Learn primary key */ + LM_LEARN_OFF_KEY, /* Learn secondary key, relevant for OM_DOUBLE */ + LM_LEARN_INITIAL, /* Learn initial pulse length, 10ms steps */ + LM_LEARN_DUTY, /* Learn duty cycle 0-10 */ + LM_LEARN_OP_MODE, /* Learn operation mode */ + LM_END, /* Only a label */ +}; + +struct config { + uint8_t magic; /* Magic value */ + enum op_mode op_mode; + uint8_t decoder_on; + uint8_t key_on; + uint8_t decoder_off; + uint8_t key_off; + uint8_t initial_pulse; /* Lenghth of initial pulse in 10ms steps */ + uint8_t on_duty_cycle; /* Duty cycle for on. 0-10 */ +}; + +static struct EEMEM config ee_config; +static struct config config; +static volatile enum learn_mode learn_mode = LM_LEARN_ON_KEY; + +static void load_config(void) { - setpin(LED, 1); - _delay_ms(20); - setpin(LED, 0); - _delay_ms(980); - GIFR |= _BV(PCIF); + eeprom_read_block(&config, &ee_config, sizeof(config)); } - -static void one(void) +static void save_config(void) { - setpin(LED, 1); - _delay_ms(20); - setpin(LED, 0); - _delay_ms(160); - setpin(LED, 1); - _delay_ms(20); - setpin(LED, 0); - _delay_ms(800); - GIFR |= _BV(PCIF); + eeprom_write_block(&config, &ee_config, sizeof(config)); } -static void trigger(void) -{ - return; - setpin(DRIVE, 1); - _delay_us(20); - setpin(DRIVE, 0); -} - -static volatile uint8_t our_decoder = 3; -static volatile uint8_t our_key = 5; -static volatile uint8_t learn_mode = 0; static volatile uint8_t drive_on = 0; -ISR(TIMER0_COMPA_vect) { - - STOP_TIMER0; - - shift_decoder <<= 1; - if (shift_zero & 2) - shift_decoder |= 1; - shift_zero <<= 1; - if (shift_sub & 0x80) - shift_zero |= 1; - shift_sub <<= 1; - if (SIGIN) - shift_sub |= 1; - - bitno++; - - if (bitno == 18) { /* Save first received word */ - shift_sub_first = shift_sub; - shift_decoder_first = shift_decoder; - } else 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 (decoder) { - /* Congratulations, we have a valid command */ - trigger(); - - if (learn_mode) { - if (command) { - our_decoder = decoder; - our_key = command; - learn_mode = 0; - eeprom_write_byte(&ee_our_decoder, our_decoder); - eeprom_write_byte(&ee_our_key, our_key); - } - } else { - if (decoder == our_decoder) { - if (command == our_key) - drive_on = 1; - if (command == 0) - drive_on = 0; - } - } - } - } - } -} -#define START_TIMER0 ({TCNT0 = 0; TCCR0B = 2;}) -#define START_TIMER1 ({TCNT1 = 1; TCCR1 = 7; GTCCR |= 2;}) -#define STOP_TIMER1 ({TCCR1 = 0; TCNT1 = 1;}) +ISR(PCINT0_vect){ + static uint8_t btn_last = 0; + mm_pinchange_handler(); -ISR(TIM1_OVF_vect) -{ - STOP_TIMER1; - // if (!SIGIN) - // setpin(LED, 1); - bitno = 0; - MON_TIMEOUT(1); + if (BTN_PRESSED && !btn_last) { + learn_mode++; + learn_mode %= LM_END; + } + btn_last = BTN_PRESSED; } -ISR(TIM0_OVF_vect) +void mm_switch_command(uint8_t decoder, uint8_t command) { - while(1) { - setpin(LED, 1); - _delay_ms(30); - setpin(LED, 1); - _delay_ms(30); - } - -} + static uint8_t toggle_lock = 0; + switch(learn_mode) { + + case LM_OFF: + default: + if ((decoder == config.decoder_on) && + (command == config.key_on)) { /* Primary key pressed */ + switch(config.op_mode) { + case OM_MOMENTARY: + case OM_DOUBLE: + drive_on = 1; + break; + case OM_TOGGLE: + if (!toggle_lock) { + drive_on = !drive_on; + toggle_lock = 1; + } + break; + default: + break; + } + } -/* Shortest element seen 184 clocks */ -/* Officially 208 clocks */ -/* (1 + 7) * 208 clocks */ + if ((decoder == config.decoder_on) && + (command == 0)) { /* Primary key released */ + switch(config.op_mode) { + case OM_MOMENTARY: + drive_on = 0; + break; + case OM_TOGGLE: + toggle_lock = 0; + break; + default: + break; + } + } -/* Pin change interrupt vector */ -ISR(PCINT0_vect) -{ - START_TIMER1; - MON_TIMEOUT(0); + if ((decoder == config.decoder_off) && + (command == config.key_off)) { /* Secondary "off" key pressed */ + switch(config.op_mode) { + case OM_DOUBLE: + drive_on = 0; + break; + case OM_TOGGLE: + case OM_MOMENTARY: + default: + break; + + } + } + break; + + case LM_LEARN_ON_KEY: + if (command) { + config.decoder_on = decoder; + config.key_on = command; + save_config(); + if (config.op_mode == OM_DOUBLE) + learn_mode = LM_LEARN_OFF_KEY; + else + learn_mode = LM_OFF; + } + break; + + case LM_LEARN_OFF_KEY: + if (command) { + config.decoder_off = decoder; + config.key_off = command; + save_config(); + learn_mode = LM_OFF; + } + break; + + case LM_LEARN_INITIAL: + if (drive_on) { + if (command == 0) + drive_on = 0; + + } else { + switch(command) { + case 1: + if (config.initial_pulse >= 10) + config.initial_pulse -= 10; + else + config.initial_pulse = 0; + save_config(); + drive_on = 1; + break; + case 2: + if (config.initial_pulse <= 245) + config.initial_pulse += 10; + else + config.initial_pulse = 255; + save_config(); + drive_on = 1; + break; + default: + break; + } + } + break; - if (SIGIN) { - START_TIMER0; + case LM_LEARN_DUTY: + if (drive_on) { + if (command == 0) + drive_on = 0; + } else { + switch(command) { + case 1: + if (config.on_duty_cycle > 0) + config.on_duty_cycle -= 1; + save_config(); + drive_on = 1; + break; + case 2: + if (config.on_duty_cycle < 10) + config.on_duty_cycle += 1; + save_config(); + drive_on = 1; + break; + default: + break; + } + } + break; + + case LM_LEARN_OP_MODE: + switch(command) { + case 1: + config.op_mode = OM_MOMENTARY; + save_config(); + learn_mode = LM_OFF; + break; + case 3: + config.op_mode = OM_DOUBLE; + save_config(); + learn_mode = LM_OFF; + break; + case 5: + config.op_mode = OM_TOGGLE; + save_config(); + learn_mode = LM_OFF; + break; + default: + break; + } + break; + } } - /****************************************************************************** * * main() - The main routine @@ -237,44 +260,91 @@ ISR(PCINT0_vect) */ int main(void) { - uint8_t duty = 30; - uint8_t old_drive = 0; + uint8_t learn_mode_off; + uint8_t drive_last = 0; + uint8_t drive_slope = 0; + uint8_t i; + setup_hw(); - our_decoder = eeprom_read_byte(&ee_our_decoder); - our_key = eeprom_read_byte(&ee_our_key); - if (our_decoder == 0xff) - learn_mode = 1; + load_config(); + + if (config.op_mode == OM_ERASED || config.magic != EE_MAGIC) { + config.magic = EE_MAGIC; + config.op_mode = OM_MOMENTARY; + // config.decoder_on = 1; + // config.key_on = 1; + config.decoder_off = 1; + config.key_off = 2; + config.initial_pulse = 10; + config.on_duty_cycle = 5; + learn_mode = LM_LEARN_ON_KEY; + } sei(); - uint8_t i; + while (1) { - if (!learn_mode) { - if (old_drive == 0 && drive_on) { - setpin(DRIVE, 1); - _delay_ms(100); + + drive_start: + + cli(); + if (!drive_last && drive_on) + drive_slope = 1; + else + drive_slope = 0; + drive_last = drive_on; + sei(); + if (drive_on) { + if (drive_slope) { + for (i = 0; i < config.initial_pulse; i++) { + setpin(PIN_DRIVE, 1); + _delay_ms(10); + } } - old_drive = drive_on; - setpin(DRIVE, drive_on); - for (i = 0; i < duty; i++) - _delay_us(4); - for (i = 0; i < (255 - duty); i++) { - setpin(DRIVE, 0); - _delay_us(4); + + for (i = 0; i < config.on_duty_cycle; i++) { + setpin(PIN_DRIVE, drive_on); + _delay_us(2); } - if (!PINVAL(BTN)) - learn_mode = 1; + for (i = 0; i < (10 - config.on_duty_cycle); i++) { + setpin(PIN_DRIVE, 0); + _delay_us(2); + } + } else { - setpin(LED, 1); - _delay_ms(30); - setpin(LED, 0); - _delay_ms(600); - } + if (!learn_mode) + continue; -/* Main loop here */ + learn_mode_off = !learn_mode; + + //if (drive_on || (learn_mode && learn_mode_off)) + // goto drive_start; + + for (i = 0; i < learn_mode; i++) { + setpin(PIN_LED, 1); + _delay_ms(30); + setpin(PIN_LED, 0); + _delay_ms(280); + + //if (drive_on || (learn_mode && learn_mode_off)) + // goto drive_start; + //if (drive_on || (learn_mode && learn_mode_off)) + // goto drive_start; + } + for (i = 0; i < 15 - learn_mode; i++) { + //if (drive_on || (learn_mode && learn_mode_off)) + // goto drive_start; + setpin(PIN_LED, 0); + _delay_ms(80); + //if (drive_on || (learn_mode && learn_mode_off)) + // goto drive_start; + // _delay_ms(40); + } + } } return 0; } + /****************************************************************************** * The end :-) */ diff --git a/trennfix/sw/mm_lookup.h b/trennfix/sw/mm_lookup.h deleted file mode 100644 index be68dfb..0000000 --- a/trennfix/sw/mm_lookup.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef __MM_LOOKUP_H -#define __MM_LOOKUP_H - -/* - * Lookup decoder number. - * - */ -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: - return 0; - } -} - -static uint8_t lookup_command(uint8_t mm_byte) -{ - switch(mm_byte) { - case 0xc3: return 1; - case 0x03: return 2; - case 0xf3: return 3; - case 0x33: return 4; - case 0xcf: return 5; - case 0x0f: return 6; - case 0xff: return 7; - case 0x3f: return 8; - default: - return 0; - } -} - - -#endif diff --git a/trennfix/sw/mm_switch.c b/trennfix/sw/mm_switch.c new file mode 100644 index 0000000..74939bf --- /dev/null +++ b/trennfix/sw/mm_switch.c @@ -0,0 +1,320 @@ +/****************************************************************************** + * + * Trennfix firmware - mm_switch.c + * + * Maerklin Motorola switch command receiver + * + * Copyright (C) 2017 Philipp Hachtmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "hardware.h" +#include "mm_switch.h" + + #define DEBUG_TIMEOUT +#ifdef DEBUG_TIMEOUT +#define MON(val) setpin(PIN_DRIVE, val) +#else +#define MON(xx) ({0;}) +#endif + + +/* + * Lookup decoder number. + * + */ +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: + return 0; + } +} + +static uint8_t lookup_command(uint8_t mm_byte) +{ + switch(mm_byte) { + case 0xc3: return 1; + case 0x03: return 2; + case 0xf3: return 3; + case 0x33: return 4; + case 0xcf: return 5; + case 0x0f: return 6; + case 0xff: return 7; + case 0x3f: return 8; + default: + return 0; + } +} + +static void mm_switch_init(void) +{ + /* Get rid of the 1/8 clock prescaler */ + CLKPR = (1 << CLKPCE); + CLKPR = 0; + + GIMSK |= _BV(PCIE); /* Enable pin change interrupt */ + PCMSK = _BV(PCINT4); /* PB4, Rail sense input */ + + TCCR0A = 0; /* This is normal mode */ + TCCR0B = 0; /* Timer off */ + TIMSK |= _BV(OCIE0A); /* Get a match interrupt */ + TIMSK |= _BV(TOV0); /* Overflow interrupt */ + + /* We need 13 + 45 us delay, That's 464 clocks @8MHz*/ + OCR0A = 91; /* Prescaler 8 is used */ + + /* Timer 1 for timeout */ + /* We set it to 1024us by prescaler 64 and running full 256 */ + TCCR1 = 7; + 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; + +/* We will shift from right to left. + * XXXXXXXX XX XXXXXXXX + * shift_decoder shift_zero shift_sub + * + * The bits 7 downto 2 of shift_zero are ignored. + */ + +volatile uint8_t bitno = 0; + +static void trigger(void) +{ + setpin(PIN_DRIVE, 1); + _delay_us(10); + setpin(PIN_DRIVE, 0); +} + +enum recstate { + IDLE = 0, + FIRST_FAST_SAMPLE, + FIRST_SLOW_SAMPLE, /* If clock arrives, we stay on the fast path! */ + FAST_SAMPLE, + FAST_WAIT_FOR_CLOCK, + SLOW_SAMPLE, + SLOW_WAIT_FOR_CLOCK, +}; + +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; + if (value) + shift_sub |= 1; +} + + +ISR(TIMER0_COMPA_vect) { + + static uint8_t patience = 0; + + switch(recstate) { + case FIRST_FAST_SAMPLE: + recstate = FIRST_SLOW_SAMPLE; + TSTART_CLK_TO_SAMPLE_FAST; /* Will not run out in fast! */ + break; + + case FIRST_SLOW_SAMPLE: + bitno = 0; + + case SLOW_SAMPLE: + recstate = SLOW_WAIT_FOR_CLOCK; + TSTART_CLK_TO_SAMPLE_SLOW; + break; + + case FAST_SAMPLE: + recstate = FAST_WAIT_FOR_CLOCK; + TSTART_CLK_TO_SAMPLE_FAST; + break; + + case FAST_WAIT_FOR_CLOCK: /* A timeout! */ + if (patience) { + patience--; + TSTART_CLK_TO_SAMPLE_FAST; + return; + } + recstate = IDLE; + TSTOP; + return; + + case SLOW_WAIT_FOR_CLOCK: + if (patience) { + patience--; + TSTART_CLK_TO_SAMPLE_SLOW; + return; + } + TSTOP; + recstate = IDLE; + return; + } + + shift(MM_SENSE); + bitno++; + + if (bitno == 18) { /* Save first received word */ + shift_sub_first = shift_sub; + shift_decoder_first = shift_decoder; + 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); + } + } + } + } +} + +ISR(BADISR_vect) +{ + while(1) { + /* + setpin(PIN_LED, 1); + _delay_ms(30); + setpin(PIN_LED, 0); + _delay_ms(30); + setpin(PIN_LED, 1); + _delay_ms(30); + setpin(PIN_LED, 0); + _delay_ms(2000); + */ + } +} + +ISR(TIM0_OVF_vect) +{ + return; + while(1) { + setpin(PIN_LED, 1); + _delay_ms(30); + setpin(PIN_LED, 0); + _delay_ms(300); + } + +} + + +/* Pin change interrupt vector */ +void mm_pinchange_handler(void) +{ + static uint8_t sense_last; + + if (MM_SENSE == sense_last) + return; + sense_last = MM_SENSE; + if (!sense_last) + return; + + switch(recstate) { + case IDLE: + bitno = 0; + recstate = FIRST_FAST_SAMPLE; + TSTART_CLK_TO_SAMPLE_FAST; + break; + case FIRST_SLOW_SAMPLE: + recstate = FAST_SAMPLE; + TSTART_CLK_TO_SAMPLE_FAST; + break; + case FAST_WAIT_FOR_CLOCK: + recstate = FAST_SAMPLE; + TSTART_CLK_TO_SAMPLE_FAST; + break; + case SLOW_WAIT_FOR_CLOCK: + recstate = SLOW_SAMPLE; + TSTART_CLK_TO_SAMPLE_SLOW; + break; + + /* Not expected */ + case FIRST_FAST_SAMPLE: + case FAST_SAMPLE: + case SLOW_SAMPLE: + default: + break; + } +} + +/****************************************************************************** + * The end :-) + */ + + + diff --git a/trennfix/sw/mm_switch.h b/trennfix/sw/mm_switch.h new file mode 100644 index 0000000..c307766 --- /dev/null +++ b/trennfix/sw/mm_switch.h @@ -0,0 +1,35 @@ +#ifndef MM_SWITCH_H +#define MM_SWITCH_H + +#include + +/* + * mm_switch_command - Callback function! + * + * This function must be defined whenever the mm_switch module is used. + * It will be called from interrupt context whenever a new valid command + * has arrived. + * + * decoder is in the range from 1 to 25. Other values will not occur. + * + * key is in the range from 0 to 8: + * + * 1 - key1 green pressed + * 2 - key1 red pressed + * 3 - key2 green pressed + * 4 - key2 red pressed + * ... + * 0 - all keys up + * + */ +void mm_switch_command(uint8_t decoder, uint8_t key); + +void mm_pinchange_handler(void); + +void mm_init(void); + + + + + +#endif diff --git a/trennfix/sw/pin_magic.h b/trennfix/sw/pin_magic.h index f335e14..a6d0b4b 100644 --- a/trennfix/sw/pin_magic.h +++ b/trennfix/sw/pin_magic.h @@ -1,6 +1,8 @@ #ifndef __HACHTIS_PIN_MAGIC_H #define __HACHTIS_PIN_MAGIC_H +#include + struct __ph_pin__ { volatile uint8_t *addr; uint8_t bitno; @@ -8,8 +10,6 @@ struct __ph_pin__ { #define _PIN(port, bit) ((volatile struct __ph_pin__){&port, bit}) -#define LED _PIN(PORTB, PORTB2) - #define OUTPUT_PIN(pin) (*(pin.addr - 1) |= _BV(pin.bitno)) #define INPUT_PIN(pin) (*(pin.addr - 1) &= ~_BV(pin.bitno))