Working in 2K single timer both mm speeds on both attiny25 and attiny85.
With PWM
Signed-off-by: Philipp Hachtmann <hachti@hachti.de>
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
-AVRDUDE_FLAGS += -B 2
+AVRDUDE_FLAGS += -B 6
#---------------- Debugging Options ----------------
#define PIN_LED _PIN(PORTB, PORTB2)
#define PIN_SENSE _PIN(PORTB, PORTB4)
#define PIN_DRIVE _PIN(PORTB, PORTB3)
-//#define PIN_DRIVE PIN_LED
#define PIN_BTN _PIN(PORTB, PB1)
-
+#define PIN_TRIGGER _PIN(PORTB, PB0)
#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;})
+#define PWM_CYCLE 21
+
static inline void setup_hw(void)
{
/* Turn off the 1/8 clock prescaler - now running at 16MHz*/
INPUT_PIN(PIN_BTN);
OUTPUT_PIN(PIN_DRIVE);
OUTPUT_PIN(PIN_LED);
+ OUTPUT_PIN(PIN_TRIGGER);
setpin(PIN_BTN, 1); /* Need pullup */
GIMSK |= _BV(PCIE); /* Enable pin change interrupt for sense port */
/* Setup timer 0, used for mm_switch */
TCCR0A = 0; /* Normal mode */
- TCCR0B = 0; /* Timer off */
+ TCCR0B = 2; /* Prescaler 8 */
TIMSK |= _BV(OCIE0A); /* Get a match interrupt */
+ OCR0A = 100; TCCR0B = 2;
#ifdef WITH_PWM
/* Timer 1 as PWM */
- OCR1C = 14;
- OCR1B = 14;
- TCCR1 = 0x6;
+ OCR1C = PWM_CYCLE;
+ OCR1B = PWM_CYCLE;
+ TCCR1 = 0x5;
+
GTCCR |= _BV(PWM1B) | _BV(COM1B0);
#endif
* Can be altered to use the LED.
*
*/
-static void __attribute__((unused)) trigger(void)
+static inline void __attribute__((unused)) trigger(void)
+{
+ setpin(PIN_TRIGGER, 1);
+ setpin(PIN_TRIGGER, 0);
+}
+
+
+static inline void __attribute__((unused)) trigger_on(void)
+{
+ setpin(PIN_TRIGGER, 1);
+}
+
+static inline void __attribute__((unused)) trigger_off(void)
{
- setpin(PIN_DRIVE, 1);
- _delay_us(4);
- setpin(PIN_DRIVE, 0);
- _delay_us(4);
+ setpin(PIN_TRIGGER, 0);
}
/*
* Configuration for mm receiver code.
*/
-
#define MM_SENSE (!PINVAL(PIN_SENSE))
-#define MM_TSTART ({TCNT0 = 0; GTCCR |= 1; OCR0A = 115; TCCR0B = 2;})
#define MM_TIMER_INT_VECT TIMER0_COMPA_vect
-/* Costs 38 bytes program memory */
-#define MM_FILTER_REPEATED
-#define USE_EEPROM_UPDATE
+#define MM_TSTART { \
+ GTCCR |= _BV(TSM) | _BV(PSR0); \
+ TCNT0 = 0; \
+ TIFR |= _BV(OCF0A); \
+ GTCCR &= ~_BV(TSM); \
+ }
+
#ifdef USE_REGISTER_VARS
uint8_t register drive_on asm("r8");
#define PINON(pin) (*pin.addr |= _BV(pin.bitno))
#define PINOFF(pin) (*pin.addr &= ~_BV(pin.bitno))
-#define PINVAL(pin) (*(pin.addr - 2) & _BV(pin.bitno) ? 1 : 0)
+//#define PINVAL(pin) (*(pin.addr - 2) & _BV(pin.bitno) ? 1 : 0)
+#define PINVAL(pin) (*(pin.addr - 2) & _BV(pin.bitno))
#define setpin(pin, val) ((val) ? PINON(pin) : PINOFF(pin))
EFUSE=0xff
#CFLAGS+= -DMM_FILTER_REPEATED
-CFLAGS+= -DMM_USE_REGISTER_VARS
-
CFLAGS+= -DUSE_REGISTER_VARS
CFLAGS+= -DWITH_EEPROM_UPDATE
CFLAGS+= -DWITH_PWM
#define MM_SWITCH_H
#include <stdint.h>
+#include <config/hardware.h>
enum mm_recstate {
MM_IDLE = 0,
void mm_switch_drive(uint8_t decoder, uint8_t function, uint8_t command);
-void mm_pinchange_handler(void);
-
+void mm_switch_pinchange_callback(void);
#endif
#include <config/hardware.h>
#include <mm/mm_switch.h>
-/*
- * Private data types
- */
-
/*
*
static uint8_t function_last = 0xff;
static uint8_t command_last = 0xff;
#endif
-
MM_TSTART;
switch(recstate) {
recstate = MM_SLOW_WAIT_FOR_CLOCK_DELAY;
break;
+ case MM_SLOW_WAIT_FOR_CLOCK_DELAY:
+ recstate = MM_SLOW_WAIT_FOR_CLOCK;
+ return;
+
case MM_FAST_SAMPLE:
recstate = MM_FAST_WAIT_FOR_CLOCK;
break;
case MM_FAST_WAIT_FOR_CLOCK: /* A timeout! */
- if (mm_rec_tolerated_timeouts) {
+ if (mm_rec_tolerated_timeouts)
mm_rec_tolerated_timeouts--;
- } else {
+ else
recstate = MM_IDLE;
-
- }
return;
case MM_SLOW_SAMPLE_DELAY:
recstate = MM_SLOW_SAMPLE;
return;
- case MM_SLOW_WAIT_FOR_CLOCK_DELAY:
- recstate = MM_SLOW_WAIT_FOR_CLOCK;
- return;
-
case MM_SLOW_WAIT_FOR_CLOCK:
if (mm_rec_tolerated_timeouts) {
- trigger();
mm_rec_tolerated_timeouts--;
recstate = MM_SLOW_WAIT_FOR_CLOCK_DELAY;
return;
case MM_IDLE:
return;
}
-
+
shift(MM_SENSE);
bitno++;
shift_function_first = shift_function;
shift_command_first = shift_command;
mm_rec_tolerated_timeouts = 18;
- trigger();
+
}
if (bitno == 36) {
if ((shift_command == shift_command_first) &&
(shift_address == shift_address_first) &&
(shift_function == shift_function_first)) {
+
#ifdef MM_FILTER_REPEATED
if ((shift_address != address_last) || (shift_command != command_last) ||
shift_function != function_last) {
#endif
address = lookup_decoder(shift_address);
-
if (recstate == MM_SLOW_WAIT_FOR_CLOCK_DELAY) {
- trigger();
mm_switch_drive(address, shift_function, shift_command);
} else if (recstate == MM_FAST_WAIT_FOR_CLOCK) {
- trigger();
command = lookup_command(shift_command);
mm_switch_command(address, command);
}
+ recstate = MM_IDLE;
#ifdef MM_FILTER_REPEATED
}
address_last = shift_address;
}
+uint8_t register sense_last asm("r9");
+
+
/* Pin change interrupt vector */
-void mm_pinchange_handler(void)
-{
+ISR(PCINT0_vect){
static uint8_t sense_last;
-
- if (MM_SENSE == sense_last)
- return;
+ if (MM_SENSE && !sense_last) {
+ MM_TSTART;
+ switch(recstate) {
+ case MM_IDLE:
+ bitno = 0;
+ recstate = MM_FIRST_FAST_SAMPLE;
+ break;
+
+ case MM_FIRST_SLOW_SAMPLE:
+ recstate = MM_FAST_SAMPLE;
+ break;
+
+ case MM_FAST_WAIT_FOR_CLOCK:
+ recstate = MM_FAST_SAMPLE;
+ mm_rec_tolerated_timeouts = 0;
+ break;
+
+ case MM_SLOW_WAIT_FOR_CLOCK_DELAY: /* If clock comes early */
+ recstate = MM_SLOW_SAMPLE_DELAY;
+ break;
+
+ case MM_SLOW_WAIT_FOR_CLOCK:
+ recstate = MM_SLOW_SAMPLE_DELAY;
+ mm_rec_tolerated_timeouts = 0;
+ break;
+
+ case MM_SLOW_SAMPLE_DELAY:
+ recstate = MM_SLOW_SAMPLE;
+ break;
+
+ /* Not expected */
+ case MM_FIRST_FAST_SAMPLE:
+ case MM_FAST_SAMPLE:
+ case MM_SLOW_SAMPLE:
+ recstate = MM_IDLE;
+ default:
+ break;
+ }
+ }
sense_last = MM_SENSE;
- if (!sense_last)
- return;
-
- MM_TSTART;
-
- switch(recstate) {
- case MM_IDLE:
- bitno = 0;
- recstate = MM_FIRST_FAST_SAMPLE;
- break;
-
- case MM_FIRST_SLOW_SAMPLE:
- recstate = MM_FAST_SAMPLE;
- break;
-
- case MM_FAST_WAIT_FOR_CLOCK:
- recstate = MM_FAST_SAMPLE;
- mm_rec_tolerated_timeouts = 0;
- break;
-
- case MM_SLOW_WAIT_FOR_CLOCK_DELAY: /* If clock comes early */
- recstate = MM_SLOW_WAIT_FOR_CLOCK;
- break;
+ mm_switch_pinchange_callback();
+ }
- case MM_SLOW_WAIT_FOR_CLOCK:
- recstate = MM_SLOW_SAMPLE_DELAY;
- mm_rec_tolerated_timeouts = 0;
- break;
-
- case MM_SLOW_SAMPLE_DELAY:
- recstate = MM_SLOW_SAMPLE;
- break;
- /* Not expected */
- case MM_FIRST_FAST_SAMPLE:
- case MM_FAST_SAMPLE:
- case MM_SLOW_SAMPLE:
- recstate = MM_IDLE;
- default:
- break;
- }
+void __attribute__((weak))mm_switch_pinchange_callback(void)
+{
}
void __attribute__((weak))mm_switch_drive(uint8_t decoder, uint8_t function,
uint8_t command)
{
- while(1);
}
void __attribute__((weak))mm_switch_command(uint8_t address, uint8_t command)
uint16_t c;
TCCR1 = 0x8;
OCR1C = divisor;
- OCR1B = divisor / 2;
+ c = (divisor * 2) / 3;
+ OCR1B = c;
for (c = 0; c < duration - pause; c++)
_delay_ms(2);
- OCR1B = 255;
- OCR1C = 14;
+ TCCR1 = 0x6;
+ OCR1C = PWM_CYCLE;
+ OCR1B = 12;
for (c = 0; c < pause; c++)
_delay_ms(2);
TCCR1 = 0x6;
- OCR1C = 14;
- OCR1B = 14;
+ OCR1C = PWM_CYCLE;
+ OCR1B = PWM_CYCLE;
}
static void tone_enter(void)
static void snd_off(void)
{
TCCR1 = 0x6;
- OCR1C = 14;
- OCR1B = 14;
+ OCR1C = PWM_CYCLE;
+ OCR1B = PWM_CYCLE;
}
#else
#endif
}
-ISR(PCINT0_vect){
+void mm_switch_pinchange_callback(void)
+{
static uint8_t btn_last = 0;
- mm_pinchange_handler();
-
if (BTN_PRESSED && !btn_last) {
config.learn_mode++;
config.learn_mode %= LM_END;
static uint8_t get_speed(uint8_t command)
{
- uint8_t b1, b3, b5, b7;
+ uint8_t b1, b3, b5, b7;
b1 = ((command & 0x80) != 0);
b3 = ((command & 0x20) != 0);
//if ((b1 != b2) || (b2 != b3) || (b3 != b4) || (b5 != b6) || (b7 != b8))
// return 0xff;
-
- return (b1 + b3*2 + b5*4 +b7*8);
+ return (b1 + b3 * 2 + b5 * 4 +b7 * 8);
}
}
alert_last = (speed == 1);
break;
+
case 50:
if (speed)
- speed -= 1;
-
+ speed = speed - 1;
+
if (config.learn_mode == LM_EASY_MODE) {
config.initial_pulse = speed;
}
break;
case 51:
+ if (speed)
+ speed = speed - 1;
+
if (config.learn_mode == LM_EASY_MODE)
config.on_duty_cycle = speed;
break;
void shift(uint8_t mu);
#ifdef WITH_PWM
-#define DRIVE_OFF {OCR1B = 14;}
-#define DRIVE_ON {OCR1B = 14 - config.on_duty_cycle;}
+#define DRIVE_OFF {OCR1B = PWM_CYCLE;}
+#define DRIVE_ON {OCR1B = PWM_CYCLE - config.on_duty_cycle;}
#define DRIVE_FULL {OCR1B = 0;}
#else
#define DRIVE_OFF {setpin(PIN_DRIVE, 0);}
uint8_t drive_slope = 0;
#endif
-
#ifdef USE_REGISTER_VARS
drive_on = 0;
#endif
config.learn_mode = LM_LEARN_ON_KEY;
}
sei();
-
while (1) {
drive_start:
config.learn_mode > LM_LEARN_OP_MODE)
continue;
-
for (i = 0; i < config.learn_mode; i++) {
setpin(PIN_LED, 1);
snd_on();