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"
36 #define LED _PIN(PORTB, PORTB2)
37 #define SENSE _PIN(PORTB, PORTB4)
38 #define DRIVE _PIN(PORTB, PORTB3)
39 #define BTN _PIN(PORTB, PB1)
41 #define SIGIN (!PINVAL(SENSE))
43 #define BTN_PRESSED (PINVAL(BTN))
45 // #define DEBUG_TIMEOUT
48 #define MON_TIMEOUT(val) setpin(DRIVE, val)
50 #define MON_TIMEOUT(xx) ({0;})
56 * Lookup decoder number.
60 static uint8_t get_decoder(uint8_t mm_byte
)
97 static uint8_t get_command(uint8_t mm_byte
)
113 static void setup_hw(void)
115 /* Get rid of the 1/8 clock prescaler */
116 CLKPR
= (1 << CLKPCE
);
123 setpin(BTN
, 1); /* Need pullup */
124 _delay_ms(1); /* Let the line rise */
127 GIMSK
|= _BV(PCIE
); /* Enable pin change interrupt */
128 PCMSK
= _BV(PCINT4
); /* PB4, Rail sense input */
130 TCCR0A
= 0; /* This is normal mode */
131 TCCR0B
= 0; /* Timer off */
132 TIMSK
|= _BV(OCIE0A
); /* Get a match interrupt */
133 TIMSK
|= _BV(TOV0
); /* Overflow interrupt */
135 /* We need 13 + 45 us delay, That's 464 clocks @8MHz*/
136 OCR0A
= 91; /* Prescaler 8 is used */
138 /* Timer 1 for timeout */
139 /* We set it to 1024us by prescaler 64 and running full 256 */
141 TIMSK
|= _BV(TOIE1
); /* Overflow interrupt */
144 static uint8_t ctr
= 0;
146 static volatile uint8_t shift_sub
;
147 static volatile uint8_t shift_zero
;
148 static volatile uint8_t shift_decoder
;
149 static volatile uint8_t shift_sub_first
;
150 static volatile uint8_t shift_decoder_first
;
152 /* We will shift from right to left.
153 * XXXXXXXX XX XXXXXXXX
154 * shift_decoder shift_zero shift_sub
156 * The bits 7 downto 2 of shift_zero are ignored.
159 #define STOP_TIMER0 (TCCR0B = 0)
161 volatile uint8_t bitno
= 0;
164 static void zero(void)
174 static void one(void)
187 static void trigger(void)
194 static volatile uint8_t our_decoder
= 3;
195 static volatile uint8_t our_key
= 5;
196 static volatile uint8_t learn_mode
= 0;
198 ISR(TIMER0_COMPA_vect
) {
206 if (shift_sub
& 0x80)
214 if (bitno
== 18) { /* Save first received word */
215 shift_sub_first
= shift_sub
;
216 shift_decoder_first
= shift_decoder
;
217 } else if (bitno
== 36) {
219 if ((shift_sub
== shift_sub_first
) &&
220 (shift_decoder
== shift_decoder_first
)) {
221 uint8_t decoder
= get_decoder(shift_decoder
);
222 uint8_t command
= get_command(shift_sub
);
224 /* Congratulations, we have a valid command */
229 our_decoder
= decoder
;
235 if (decoder
== our_decoder
) {
236 if (command
== our_key
)
247 #define START_TIMER0 ({TCNT0 = 0; TCCR0B = 2;})
248 #define START_TIMER1 ({TCNT1 = 1; TCCR1 = 7; GTCCR |= 2;})
249 #define STOP_TIMER1 ({TCCR1 = 0; TCNT1 = 1;})
271 /* Shortest element seen 184 clocks */
272 /* Officially 208 clocks */
273 /* (1 + 7) * 208 clocks */
275 /* Pin change interrupt vector */
288 /******************************************************************************
290 * main() - The main routine
297 // while(PINVAL(BTN));
315 /******************************************************************************