1 /******************************************************************************
3 * Trennfix firmware - main.c
5 * Copyright (C) 2017 Philipp Hachtmann
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *****************************************************************************/
27 #include <avr/eeprom.h>
28 #include <avr/interrupt.h>
29 #include <avr/pgmspace.h>
31 #include <util/delay.h>
34 #include "pin_magic.h"
35 #include "mm_lookup.h"
37 #define LED _PIN(PORTB, PORTB2)
38 #define SENSE _PIN(PORTB, PORTB4)
39 #define DRIVE _PIN(PORTB, PORTB3)
40 #define BTN _PIN(PORTB, PB1)
42 #define SIGIN (!PINVAL(SENSE))
43 #define BTN_PRESSED (!PINVAL(BTN))
45 // #define DEBUG_TIMEOUT
47 #define MON_TIMEOUT(val) setpin(DRIVE, val)
49 #define MON_TIMEOUT(xx) ({0;})
52 uint8_t EEMEM ee_our_decoder
;
53 uint8_t EEMEM ee_our_key
;
55 static void setup_hw(void)
57 /* Get rid of the 1/8 clock prescaler */
58 CLKPR
= (1 << CLKPCE
);
65 setpin(BTN
, 1); /* Need pullup */
66 _delay_ms(1); /* Let the line rise */
69 GIMSK
|= _BV(PCIE
); /* Enable pin change interrupt */
70 PCMSK
= _BV(PCINT4
); /* PB4, Rail sense input */
72 TCCR0A
= 0; /* This is normal mode */
73 TCCR0B
= 0; /* Timer off */
74 TIMSK
|= _BV(OCIE0A
); /* Get a match interrupt */
75 TIMSK
|= _BV(TOV0
); /* Overflow interrupt */
77 /* We need 13 + 45 us delay, That's 464 clocks @8MHz*/
78 OCR0A
= 91; /* Prescaler 8 is used */
80 /* Timer 1 for timeout */
81 /* We set it to 1024us by prescaler 64 and running full 256 */
83 TIMSK
|= _BV(TOIE1
); /* Overflow interrupt */
86 static uint8_t ctr
= 0;
88 static volatile uint8_t shift_sub
;
89 static volatile uint8_t shift_zero
;
90 static volatile uint8_t shift_decoder
;
91 static volatile uint8_t shift_sub_first
;
92 static volatile uint8_t shift_decoder_first
;
94 /* We will shift from right to left.
95 * XXXXXXXX XX XXXXXXXX
96 * shift_decoder shift_zero shift_sub
98 * The bits 7 downto 2 of shift_zero are ignored.
101 #define STOP_TIMER0 (TCCR0B = 0)
103 volatile uint8_t bitno
= 0;
106 static void zero(void)
116 static void one(void)
129 static void trigger(void)
137 static volatile uint8_t our_decoder
= 3;
138 static volatile uint8_t our_key
= 5;
139 static volatile uint8_t learn_mode
= 0;
140 static volatile uint8_t drive_on
= 0;
142 ISR(TIMER0_COMPA_vect
) {
150 if (shift_sub
& 0x80)
158 if (bitno
== 18) { /* Save first received word */
159 shift_sub_first
= shift_sub
;
160 shift_decoder_first
= shift_decoder
;
161 } else if (bitno
== 36) {
163 if ((shift_sub
== shift_sub_first
) &&
164 (shift_decoder
== shift_decoder_first
)) {
165 uint8_t decoder
= lookup_decoder(shift_decoder
);
166 uint8_t command
= lookup_command(shift_sub
);
168 /* Congratulations, we have a valid command */
173 our_decoder
= decoder
;
176 eeprom_write_byte(&ee_our_decoder
, our_decoder
);
177 eeprom_write_byte(&ee_our_key
, our_key
);
180 if (decoder
== our_decoder
) {
181 if (command
== our_key
)
192 #define START_TIMER0 ({TCNT0 = 0; TCCR0B = 2;})
193 #define START_TIMER1 ({TCNT1 = 1; TCCR1 = 7; GTCCR |= 2;})
194 #define STOP_TIMER1 ({TCCR1 = 0; TCNT1 = 1;})
216 /* Shortest element seen 184 clocks */
217 /* Officially 208 clocks */
218 /* (1 + 7) * 208 clocks */
220 /* Pin change interrupt vector */
233 /******************************************************************************
235 * main() - The main routine
241 uint8_t old_drive
= 0;
243 our_decoder
= eeprom_read_byte(&ee_our_decoder
);
244 our_key
= eeprom_read_byte(&ee_our_key
);
245 if (our_decoder
== 0xff)
251 if (old_drive
== 0 && drive_on
) {
255 old_drive
= drive_on
;
256 setpin(DRIVE
, drive_on
);
257 for (i
= 0; i
< duty
; i
++)
259 for (i
= 0; i
< (255 - duty
); i
++) {
278 /******************************************************************************