trennfix/sw: Register variables, restructuring, whatever
authorPhilipp Hachtmann <hachti@hachti.de>
Sat, 11 Feb 2017 03:17:38 +0000 (04:17 +0100)
committerPhilipp Hachtmann <hachti@hachti.de>
Sun, 12 Feb 2017 17:04:25 +0000 (18:04 +0100)
Signed-off-by: Philipp Hachtmann <hachti@hachti.de>
trennfix/sw/Makefile
trennfix/sw/config/trennfix_attiny25.h
trennfix/sw/config/trennfix_attiny25.mk [deleted file]
trennfix/sw/config/trennfix_attiny85.mk [deleted file]
trennfix/sw/mk/trennfix_attiny25.mk [new file with mode: 0644]
trennfix/sw/mk/trennfix_attiny85.mk [new file with mode: 0644]
trennfix/sw/mm/include/mm/mm_switch.h
trennfix/sw/mm/src/mm_switch.c
trennfix/sw/src/main.c

index 5f3774f61d99464686ecaf70baacefff6be1be7a..07546bdf97d8e857eb0de139d0ed6568c5a60c92 100644 (file)
@@ -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
index a995437f657c687d282c913c62e64c2773f8150f..c733c71765b5adf574ce49c72ab2be376b03b9cd 100644 (file)
@@ -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 (file)
index 466277b..0000000
+++ /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 (file)
index 896a008..0000000
+++ /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 (file)
index 0000000..64cd1ad
--- /dev/null
@@ -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 (file)
index 0000000..fe044a8
--- /dev/null
@@ -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
+
+
+
+
+
+
+
+
+
index fb36036b8826d6adc20cce591dafdf72d3c850e8..94655a903d1830384a3107e8f9d616b07940f2aa 100644 (file)
@@ -3,6 +3,36 @@
 
 #include <stdint.h>
 
+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
index 2b09e5cbeaf5dda4d387f85b7f488fd0373b8b3e..30f43cbaa3ddd13f0391d3e76a54cbec4c464318 100644 (file)
  *    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
+        *
+        * <aaaaaaaa><00><aabbcc11>
+        *
+        * 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:
+        * 
+        * <aaaaaaaa><00><aabbcc00> 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
+        * <aaaaaaaa>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;
        }
index 7d5c10a395f4f1e5adc73eea95750de3c71e5be3..47d051d34dacce3e486d21da22a6256932cea3d7 100644 (file)
@@ -33,7 +33,6 @@
 #include <mm/mm_switch.h>
 #include <config/hardware.h>
 
-
 #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 {