From: Philipp Hachtmann Date: Sat, 11 Feb 2017 03:17:38 +0000 (+0100) Subject: trennfix/sw: Register variables, restructuring, whatever X-Git-Url: http://gitweb.hachti.de/?a=commitdiff_plain;h=7c08d02a1ca8d88bd794787036431a6870662270;p=eisenbahn.git trennfix/sw: Register variables, restructuring, whatever Signed-off-by: Philipp Hachtmann --- diff --git a/trennfix/sw/Makefile b/trennfix/sw/Makefile index 5f3774f..07546bd 100644 --- a/trennfix/sw/Makefile +++ b/trennfix/sw/Makefile @@ -29,7 +29,7 @@ CONFIG?=trennfix_attiny25 -include config/${CONFIG}.mk +include mk/${CONFIG}.mk INCLUDES+=-I mm/include -I include SRC+= mm/src/mm_switch.c diff --git a/trennfix/sw/config/trennfix_attiny25.h b/trennfix/sw/config/trennfix_attiny25.h index a995437..c733c71 100644 --- a/trennfix/sw/config/trennfix_attiny25.h +++ b/trennfix/sw/config/trennfix_attiny25.h @@ -5,7 +5,8 @@ #define PIN_LED _PIN(PORTB, PORTB2) #define PIN_SENSE _PIN(PORTB, PORTB4) -#define PIN_DRIVE _PIN(PORTB, PORTB3) +//#define PIN_DRIVE _PIN(PORTB, PORTB3) +#define PIN_DRIVE PIN_LED #define PIN_BTN _PIN(PORTB, PB1) #define BTN_PRESSED (!PINVAL(PIN_BTN)) @@ -74,8 +75,8 @@ static void __attribute__((unused)) trigger(void) */ #define MM_SENSE (!PINVAL(PIN_SENSE)) -#define MM_TSTART_FAST ({TCNT0 = 0; GTCCR |= 1; OCR0A = 110; TCCR0B = 2;}) -#define MM_TSTART_SLOW ({TCNT0 = 0; GTCCR |= 1; OCR0A = 220; TCCR0B = 2;}) +#define MM_TSTART_FAST ({TCNT0 = 0; GTCCR |= 1; OCR0A = 120; TCCR0B = 2;}) +#define MM_TSTART_SLOW ({TCNT0 = 0; GTCCR |= 1; OCR0A = 230; TCCR0B = 2;}) #define MM_TSTOP ({TCCR0B = 0;}) #define MM_TIMER_INT_VECT TIMER0_COMPA_vect diff --git a/trennfix/sw/config/trennfix_attiny25.mk b/trennfix/sw/config/trennfix_attiny25.mk deleted file mode 100644 index 466277b..0000000 --- a/trennfix/sw/config/trennfix_attiny25.mk +++ /dev/null @@ -1,29 +0,0 @@ - -SRC = src/main.c - -################################################################################ -################################################################################ - -AVRDUDE_PROGRAMMER = avrisp2 -MCU=attiny25 -F_CPU = 16000000 - -# Fuse-Bits gibts praktisch bei http://www.engbedded.com/fusecalc ! -# 8 MHz interner RC-Oszillator usw. Brown out 4V - -LFUSE=0x61 -#HFUSE=0xdc -HFUSE=0xd4 -EFUSE=0xff - -CFLAGS+=-DONLY_2K - - - - - - - - - - diff --git a/trennfix/sw/config/trennfix_attiny85.mk b/trennfix/sw/config/trennfix_attiny85.mk deleted file mode 100644 index 896a008..0000000 --- a/trennfix/sw/config/trennfix_attiny85.mk +++ /dev/null @@ -1,30 +0,0 @@ - -SRC = src/main.c - -################################################################################ -################################################################################ - -AVRDUDE_PROGRAMMER = avrisp2 -MCU=attiny85 -F_CPU = 16000000 - -# Fuse-Bits gibts praktisch bei http://www.engbedded.com/fusecalc ! -# 8 MHz interner RC-Oszillator usw. Brown out 4V - -# Tiny 25 -#LFUSE=0x61 -#HFUSE=0xdc -#EFUSE=0xff - -LFUSE=0x61 -HFUSE=0xd4 -EFUSE=0xff - - - - - - - - - diff --git a/trennfix/sw/mk/trennfix_attiny25.mk b/trennfix/sw/mk/trennfix_attiny25.mk new file mode 100644 index 0000000..64cd1ad --- /dev/null +++ b/trennfix/sw/mk/trennfix_attiny25.mk @@ -0,0 +1,37 @@ + +SRC = src/main.c + +################################################################################ +################################################################################ + +AVRDUDE_PROGRAMMER = avrisp2 +MCU=attiny25 +F_CPU = 16000000 + +# Fuse-Bits gibts praktisch bei http://www.engbedded.com/fusecalc ! +# 8 MHz interner RC-Oszillator usw. Brown out 4V + +ifneq ($(KEEP_EEPROM),) + +HFUSE=0xd4 + +else + +HFUSE=0xdc + +endif + +LFUSE=0x61 +EFUSE=0xff + +CFLAGS+=-DONLY_2K -DMM_USE_REGISTER_VARS + + + + + + + + + + diff --git a/trennfix/sw/mk/trennfix_attiny85.mk b/trennfix/sw/mk/trennfix_attiny85.mk new file mode 100644 index 0000000..fe044a8 --- /dev/null +++ b/trennfix/sw/mk/trennfix_attiny85.mk @@ -0,0 +1,41 @@ + +SRC = src/main.c + + +################################################################################ +################################################################################ + +AVRDUDE_PROGRAMMER = avrisp2 +MCU=attiny85 +F_CPU = 16000000 + +# Fuse-Bits gibts praktisch bei http://www.engbedded.com/fusecalc ! +# 8 MHz interner RC-Oszillator usw. Brown out 4V + + +#LFUSE=0x61 +#HFUSE=0xdc +#EFUSE=0xff + +LFUSE=0x61 + +ifneq ($(KEEP_EEPROM),) + +HFUSE=0xd4 + +else + +HFUSE=0xdc + +endif + +EFUSE=0xff + + + + + + + + + diff --git a/trennfix/sw/mm/include/mm/mm_switch.h b/trennfix/sw/mm/include/mm/mm_switch.h index fb36036..94655a9 100644 --- a/trennfix/sw/mm/include/mm/mm_switch.h +++ b/trennfix/sw/mm/include/mm/mm_switch.h @@ -3,6 +3,36 @@ #include +enum mm_recstate { + MM_IDLE = 0, + MM_FIRST_FAST_SAMPLE, + MM_FIRST_SLOW_SAMPLE, /* If clock arrives, we stay on the fast path! */ + MM_FAST_SAMPLE, + MM_FAST_WAIT_FOR_CLOCK, + MM_SLOW_SAMPLE, + MM_SLOW_WAIT_FOR_CLOCK, +}; + +#ifdef MM_USE_REGISTER_VARS + +uint8_t register shift_command asm("r2"); +uint8_t register shift_function asm("r3"); +uint8_t register shift_address asm("r4"); +uint8_t register recstate asm("r5"); +uint8_t register bitno asm("r6"); + +static void inline __attribute((unused)) mm_init(void) +{ + bitno = 0; + recstate = MM_IDLE; +} + +#else + +#define mm_init(...) + +#endif + /* * mm_switch_command - Callback function! * @@ -33,6 +63,5 @@ void mm_switch_drive(uint8_t decoder, uint8_t function, uint8_t command); void mm_pinchange_handler(void); -void mm_init(void); #endif diff --git a/trennfix/sw/mm/src/mm_switch.c b/trennfix/sw/mm/src/mm_switch.c index 2b09e5c..30f43cb 100644 --- a/trennfix/sw/mm/src/mm_switch.c +++ b/trennfix/sw/mm/src/mm_switch.c @@ -40,15 +40,6 @@ * Private data types */ -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, -}; /* * @@ -65,12 +56,16 @@ enum recstate { /* * Private global variables */ -static volatile uint8_t shift_command; -static volatile uint8_t shift_function; -static volatile uint8_t shift_address; -static enum recstate recstate = IDLE; -volatile uint8_t bitno = 0; +#ifndef MM_USE_REGISTER_VARS + +static volatile uint8_t bitno = 0; +static uint8_t shift_command; +static uint8_t shift_function; +static uint8_t shift_address; +static enum mm_recstate recstate = MM_IDLE; + +#endif /* * Lookup trinary nibble @@ -105,30 +100,115 @@ static uint8_t lookup_decoder(uint8_t mm_byte) return 9 * high + low; } -static uint8_t lookup_command(uint8_t mm_byte) +static uint8_t lookup_command(uint8_t mm_command) { - 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: + uint8_t res; + /* + * Check for aabbccdd condition + * + * a a b b c c d d mm_command + * XOR a b b c c d d 0 mm_command << 1 + * Mask 1 0 1 0 1 0 1 0 0xaa + * + * Must be zero! + * + */ + + if ((mm_command ^ (mm_command << 1)) & 0xaa) return 0; - } + /* + * Protocol differences: + * ===================== + * + * I have an old "central control" 6022 and a "control unit" 6021 + * for measurements and test. It is assumed that the 6022 outputs + * old MM1 format while the 6021 definitively outputs MM2 telegrams. + * + * In MM1, switch commands are different from MM2 with respect what + * happens if you release a button. + * + * When you press a button, both protocols send + * + * <00> + * + * where a = 1, b = 2, c = 4 and the keys are numerated from 0 to 7 + * in the order 1 red, 1 green, 2 red, 2 green and so on. + * + * The last two bits correspond to "on" state of the button/coil. + * + * When a key is released under MM1 protocol, the sequence sent is + * analogue to the button down sequence: + * + * <00> where abc again represents the button's + * address and the last bits now signal "off". + * + * MM2 handles this differently: + * Whenever any key from the addressed decoder is released, the sequence + * 00<00000000> is sent - not only for key 0, but for all + * keys! + * + * While MM1 presents the theoretical possibility to press several keys + * independently and simultaneously (which my keyboard does NOT + * support), MM2 supports only one key at a time (besides strange + * sequences like "one down, another down, all up"... + * + * A decoder that strictly adheres to the MM1 standard would not work + * properly with MM2 control units. As far as I know all K83/K84 + * decoders always worked with MM2 control units. That means that + * they reduce the commands to the possibilities of MM2 from the + * beginning. + * + * Possible use cases for the old protocol button release commands: + * - Determine if the protocol is MM1 or MM2 + * - Implement hidden evil features into the controller which can + * only be summoned by old MM1 gear or selfmade control telegram + * generators. + * + * What this code now actually does: + * ================================= + * + * When key pressed (aabbcc11), it will send out the key number in the + * range 1-8 and 0 if it gets any key up command and therefore ignore + * the key number if it is transmitted with the key up command. + * + */ + if (!(mm_command & 0x01)) + res = 0; + else + res = (mm_command & 0x80) * 1 + (mm_command & 0x20) * 0x02 + + (mm_command & 0x08) * 0x04 + 1; + return res; } + /* We will shift from right to left. * XXXXXXXX XX XXXXXXXX * shift_address shift_function shift_command * * The bits 7 downto 2 of shift_function are ignored. */ +#define SAVE_ANOTHER_40_BYTES +#ifdef SAVE_ANOTHER_40_BYTES -static inline void shift(uint8_t value) +void shift(uint8_t value) +{ + asm("ror %[val] ; Shift value right into carry\n\t" + "rol %[cmd] ; and shift to command reg\n\t" + "mov __tmp_reg__, %[func] ; save function value \n\t" + "rol %[func] ; Shift up function value\n\t" + "ror __tmp_reg__ ; shift bit 1\n\t" + "ror __tmp_reg__ ; down to carry\n\t" + "rol %[addr] ; And we're at the address\n\t" + : [cmd] "=r" (shift_command), [func] "=r" (shift_function), + [addr] "=r" (shift_address) + : "0" (shift_command), "1" (shift_function), + "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) @@ -140,6 +220,8 @@ static inline void shift(uint8_t value) if (value) shift_command |= 1; } +#endif + ISR(MM_TIMER_INT_VECT) { static uint8_t tolerated_timeouts = 0; @@ -157,35 +239,35 @@ ISR(MM_TIMER_INT_VECT) { #endif switch(recstate) { - case FIRST_FAST_SAMPLE: - recstate = FIRST_SLOW_SAMPLE; + case MM_FIRST_FAST_SAMPLE: + recstate = MM_FIRST_SLOW_SAMPLE; MM_TSTART_FAST; /* Will not run out in fast! */ break; - case FIRST_SLOW_SAMPLE: + case MM_FIRST_SLOW_SAMPLE: bitno = 0; - case SLOW_SAMPLE: - recstate = SLOW_WAIT_FOR_CLOCK; + case MM_SLOW_SAMPLE: + recstate = MM_SLOW_WAIT_FOR_CLOCK; MM_TSTART_SLOW; break; - case FAST_SAMPLE: - recstate = FAST_WAIT_FOR_CLOCK; + case MM_FAST_SAMPLE: + recstate = MM_FAST_WAIT_FOR_CLOCK; MM_TSTART_FAST; break; - case FAST_WAIT_FOR_CLOCK: /* A timeout! */ + case MM_FAST_WAIT_FOR_CLOCK: /* A timeout! */ if (tolerated_timeouts) { tolerated_timeouts--; MM_TSTART_FAST; return; } - recstate = IDLE; + recstate = MM_IDLE; MM_TSTOP; return; - case SLOW_WAIT_FOR_CLOCK: + case MM_SLOW_WAIT_FOR_CLOCK: if (tolerated_timeouts) { tolerated_timeouts--; MM_TSTART_SLOW; @@ -193,7 +275,7 @@ ISR(MM_TIMER_INT_VECT) { } default: MM_TSTOP; - recstate = IDLE; + recstate = MM_IDLE; return; } @@ -219,9 +301,9 @@ ISR(MM_TIMER_INT_VECT) { #endif address = lookup_decoder(shift_address); - if (recstate == SLOW_WAIT_FOR_CLOCK) { + if (recstate == MM_SLOW_WAIT_FOR_CLOCK) { mm_switch_drive(address, shift_function, shift_command); - } else if (recstate == FAST_WAIT_FOR_CLOCK) { + } else if (recstate == MM_FAST_WAIT_FOR_CLOCK) { command = lookup_command(shift_command); mm_switch_command(address, command); } @@ -278,28 +360,28 @@ void mm_pinchange_handler(void) return; switch(recstate) { - case IDLE: + case MM_IDLE: bitno = 0; - recstate = FIRST_FAST_SAMPLE; + recstate = MM_FIRST_FAST_SAMPLE; MM_TSTART_FAST; break; - case FIRST_SLOW_SAMPLE: - recstate = FAST_SAMPLE; + case MM_FIRST_SLOW_SAMPLE: + recstate = MM_FAST_SAMPLE; MM_TSTART_FAST; break; - case FAST_WAIT_FOR_CLOCK: - recstate = FAST_SAMPLE; + case MM_FAST_WAIT_FOR_CLOCK: + recstate = MM_FAST_SAMPLE; MM_TSTART_FAST; break; - case SLOW_WAIT_FOR_CLOCK: - recstate = SLOW_SAMPLE; + case MM_SLOW_WAIT_FOR_CLOCK: + recstate = MM_SLOW_SAMPLE; MM_TSTART_SLOW; break; /* Not expected */ - case FIRST_FAST_SAMPLE: - case FAST_SAMPLE: - case SLOW_SAMPLE: + case MM_FIRST_FAST_SAMPLE: + case MM_FAST_SAMPLE: + case MM_SLOW_SAMPLE: default: break; } diff --git a/trennfix/sw/src/main.c b/trennfix/sw/src/main.c index 7d5c10a..47d051d 100644 --- a/trennfix/sw/src/main.c +++ b/trennfix/sw/src/main.c @@ -33,7 +33,6 @@ #include #include - #define EE_MAGIC 0xab enum op_mode { @@ -231,7 +230,7 @@ void mm_switch_command(uint8_t decoder, uint8_t command) } if ((decoder == config.decoder_on) && - (command == 0)) { /* Primary key released */ + (command == 0)) { /* Primary key released */ switch(config.op_mode) { case OM_MOMENTARY: switch_on = 0; @@ -365,6 +364,7 @@ void mm_switch_command(uint8_t decoder, uint8_t command) * main() - The main routine * */ +void shift(uint8_t mu); int main(void) { uint8_t learn_mode_off; @@ -373,6 +373,7 @@ int main(void) { uint8_t i; uint8_t output_on; + mm_init(); load_config(); setup_hw(); @@ -389,9 +390,7 @@ int main(void) { } drive_on = 0; sei(); - setpin(PIN_DRIVE, 1); - _delay_ms(50); - setpin(PIN_DRIVE, 0); + //setpin(PIN_LED,1 ); //_delay_ms(400); @@ -419,11 +418,11 @@ int main(void) { for (i = 0; i < config.on_duty_cycle; i++) { setpin(PIN_DRIVE, output_on); - _delay_us(3); + _delay_us(1); } - for (i = 0; i < (28 - config.on_duty_cycle); i++) { + for (i = 0; i < (14 - config.on_duty_cycle); i++) { setpin(PIN_DRIVE, 0); - _delay_us(3); + _delay_us(1); } } else {