#define EE_MAGIC 0xab
+static void trigger(void)
+{
+ setpin(PIN_DRIVE, 1);
+ _delay_us(10);
+ setpin(PIN_DRIVE, 0);
+}
+
enum op_mode {
OM_MOMENTARY, /* on as long as "key on" pressed */
OM_DOUBLE, /* On off with "on" and "off" keys */
static struct EEMEM config ee_config;
static struct config config;
-static volatile enum learn_mode learn_mode = LM_LEARN_ON_KEY;
+static volatile enum learn_mode learn_mode = LM_OFF;
static void load_config(void)
{
static void save_config(void)
{
- eeprom_write_block(&config, &ee_config, sizeof(config));
+ eeprom_update_block(&config, &ee_config, sizeof(config));
}
static volatile uint8_t drive_on = 0;
-
ISR(PCINT0_vect){
static uint8_t btn_last = 0;
+
mm_pinchange_handler();
if (BTN_PRESSED && !btn_last) {
btn_last = BTN_PRESSED;
}
+static uint8_t get_speed(uint8_t command)
+{
+ uint8_t b1, b2, b3, b4, b5, b6, b7, b8;
+ b1 = ((command & 0x80) != 0);
+ b2 = ((command & 0x40) != 0);
+ b3 = ((command & 0x20) != 0);
+ b4 = ((command & 0x10) != 0);
+ b5 = ((command & 0x8) != 0);
+ b6 = ((command & 0x4) != 0);
+ b7 = ((command & 0x2) != 0);
+ b8 = ((command & 0x1) != 0);
+
+ //if ((b1 != b2) || (b2 != b3) || (b3 != b4) || (b5 != b6) || (b7 != b8))
+ // return 0xff;
+
+ return (b1 + b3*2 + b5*4 +b7*8);
+}
+
+void mm_switch_drive(uint8_t decoder, uint8_t function, uint8_t command)
+{
+ static uint8_t seen_before = 0;
+ uint8_t speed;
+
+
+ if (!seen_before) {
+ // if (decoder == 100)
+ //
+
+ if ((decoder == 100) && (function == 0) && (command == 0xc0)) {
+ config.magic = 0;
+ save_config();
+ }
+ }
+ seen_before = 1;
+ speed = get_speed(command);
+ static uint8_t itsme = 0;
+ if (decoder == 10) {
+ trigger();
+
+ if (speed == 1) {
+ itsme = 1;
+ drive_on = 1;
+ }else {
+ if (itsme) {
+ drive_on = 0;
+ itsme = 0;
+ }
+ }
+ }
+ if (decoder == 33) {
+ // trigger();
+
+ speed = get_speed(command);
+ if (speed != 0xff) {
+ if (speed >= 1) speed -= 1;
+ if (speed <= 14)
+ config.on_duty_cycle = speed;
+ else
+ config.on_duty_cycle = 14;
+ }
+ }
+}
+
void mm_switch_command(uint8_t decoder, uint8_t command)
{
static uint8_t toggle_lock = 0;
case OM_MOMENTARY:
default:
break;
-
}
}
break;
}
break;
+#ifdef LEARN_THE_STUFF
case LM_LEARN_OFF_KEY:
if (command) {
config.decoder_off = decoder;
break;
}
break;
-
+#endif
}
}
*/
int main(void) {
- uint8_t learn_mode_off;
+ // uint8_t learn_mode_off;
uint8_t drive_last = 0;
uint8_t drive_slope = 0;
uint8_t i;
- setup_hw();
load_config();
+ setup_hw();
- if (config.op_mode == OM_ERASED || config.magic != EE_MAGIC) {
+ if ((config.op_mode == OM_ERASED) || (config.magic != EE_MAGIC)) {
config.magic = EE_MAGIC;
config.op_mode = OM_MOMENTARY;
- // config.decoder_on = 1;
- // config.key_on = 1;
+ config.decoder_on = 1;
+ config.key_on = 1;
config.decoder_off = 1;
config.key_off = 2;
config.initial_pulse = 10;
while (1) {
- drive_start:
+ // drive_start:
cli();
if (!drive_last && drive_on)
drive_slope = 0;
drive_last = drive_on;
sei();
+
if (drive_on) {
+#ifdef ROOM_FOR_KICK
if (drive_slope) {
for (i = 0; i < config.initial_pulse; i++) {
setpin(PIN_DRIVE, 1);
_delay_ms(10);
}
}
-
+#endif
+
+#define ROOM_FOR_PWM
+#ifdef ROOM_FOR_PWM
for (i = 0; i < config.on_duty_cycle; i++) {
setpin(PIN_DRIVE, drive_on);
- _delay_us(2);
+ _delay_us(1);
}
-
- for (i = 0; i < (10 - config.on_duty_cycle); i++) {
+ for (i = 0; i < (14 - config.on_duty_cycle); i++) {
setpin(PIN_DRIVE, 0);
- _delay_us(2);
+ _delay_us(1);
}
+#else
+ setpin(PIN_DRIVE, 1);
+#endif
+
} else {
+ setpin(PIN_DRIVE, 0);
if (!learn_mode)
continue;
- learn_mode_off = !learn_mode;
+ //learn_mode_off = !learn_mode;
//if (drive_on || (learn_mode && learn_mode_off))
// goto drive_start;
#include "hardware.h"
#include "mm_switch.h"
- #define DEBUG_TIMEOUT
+// #define DEBUG_TIMEOUT
#ifdef DEBUG_TIMEOUT
#define MON(val) setpin(PIN_DRIVE, val)
#else
* Lookup decoder number.
*
*/
+
+static uint8_t lookup_nibble(uint8_t mm_nibble)
+{
+ switch(mm_nibble) {
+ case 0x0: return 0;
+ case 0xc: return 1;
+ case 0x8: return 2;
+ case 0x3: return 3;
+ case 0xf: return 4;
+ case 0xb: return 5;
+ case 0x2: return 6;
+ case 0xe: return 7;
+ case 0xa: return 8;
+ default: return 0;
+ }
+ return 0;
+}
+
static uint8_t lookup_decoder(uint8_t mm_byte)
{
- switch(mm_byte) {
- /* 0x00 is invalid */
- case 0xc0: return 1;
- case 0x80: return 2;
- case 0x30: return 3;
- case 0xf0: return 4;
- case 0xb0: return 5;
- case 0x20: return 6;
- case 0xe0: return 7;
- case 0xa0: return 8;
-
- case 0x0c: return 9;
- case 0xcc: return 10;
- case 0x8c: return 11;
- case 0x3c: return 12;
- case 0xfc: return 13;
- case 0xbc: return 14;
- case 0x2c: return 15;
- case 0xec: return 16;
- case 0xac: return 17;
-
- case 0x08: return 18;
- case 0xc8: return 19;
- case 0x88: return 20;
- case 0x38: return 21;
- case 0xf8: return 22;
- case 0xb8: return 23;
- case 0x28: return 24;
- case 0xe8: return 25;
-
- default:
+ uint8_t low;
+ uint8_t high;
+ if (mm_byte == 0)
+ return 100;
+ low = lookup_nibble(mm_byte >> 4);
+ high = lookup_nibble(mm_byte & 0xf);
+ if (!low)
return 0;
- }
+ return 9 * high + low;
}
static uint8_t lookup_command(uint8_t mm_byte)
}
}
-static void mm_switch_init(void)
+
+static __attribute__((unused)) void mm_switch_init(void)
{
/* Get rid of the 1/8 clock prescaler */
CLKPR = (1 << CLKPCE);
TIMSK |= _BV(TOIE1); /* Overflow interrupt */
}
-
-static volatile uint8_t shift_sub;
-static volatile uint8_t shift_zero;
-static volatile uint8_t shift_decoder;
-static volatile uint8_t shift_sub_first;
-static volatile uint8_t shift_decoder_first;
+static volatile uint8_t shift_command;
+static volatile uint8_t shift_function;
+static volatile uint8_t shift_address;
+static volatile uint8_t shift_command_first;
+static volatile uint8_t shift_address_first;
/* We will shift from right to left.
* XXXXXXXX XX XXXXXXXX
- * shift_decoder shift_zero shift_sub
+ * shift_address shift_function shift_command
*
- * The bits 7 downto 2 of shift_zero are ignored.
+ * The bits 7 downto 2 of shift_function are ignored.
*/
volatile uint8_t bitno = 0;
-static void trigger(void)
+static void __attribute__((unused)) trigger(void)
{
setpin(PIN_DRIVE, 1);
- _delay_us(10);
+ _delay_us(4);
setpin(PIN_DRIVE, 0);
+ _delay_us(4);
}
enum recstate {
static inline void shift(uint8_t value)
{
- shift_decoder <<= 1;
- if (shift_zero & 2)
- shift_decoder |= 1;
- shift_zero <<= 1;
- if (shift_sub & 0x80)
- shift_zero |= 1;
- shift_sub <<= 1;
+ shift_address <<= 1;
+ if (shift_function & 2)
+ shift_address |= 1;
+ shift_function <<= 1;
+ if (shift_command & 0x80)
+ shift_function |= 1;
+ shift_command <<= 1;
if (value)
- shift_sub |= 1;
+ shift_command |= 1;
}
ISR(TIMER0_COMPA_vect) {
-
static uint8_t patience = 0;
+ static uint8_t address_last = 0xff;
+ static uint8_t function_last = 0xff;
+ static uint8_t command_last = 0xff;
switch(recstate) {
case FIRST_FAST_SAMPLE:
TSTART_CLK_TO_SAMPLE_SLOW;
return;
}
+ default:
TSTOP;
recstate = IDLE;
return;
shift(MM_SENSE);
bitno++;
-
+
if (bitno == 18) { /* Save first received word */
- shift_sub_first = shift_sub;
- shift_decoder_first = shift_decoder;
+ shift_command_first = shift_command;
+ shift_address_first = shift_address;
patience = 18;
}
+
if (bitno == 36) {
- if ((shift_sub == shift_sub_first) &&
- (shift_decoder == shift_decoder_first)) {
- uint8_t decoder = lookup_decoder(shift_decoder);
- uint8_t command = lookup_command(shift_sub);
- if (recstate == SLOW_WAIT_FOR_CLOCK)
- trigger();
- if (decoder) {
- /* Congratulations, we have a valid command */
- if (recstate == FAST_WAIT_FOR_CLOCK) {
- // trigger();
- mm_switch_command(decoder, command);
+ if ((shift_command == shift_command_first) &&
+ (shift_address == shift_address_first)) {
+ if ((shift_address != address_last) || (shift_command != command_last) ||
+ shift_function != function_last) {
+
+ uint8_t addr = lookup_decoder(shift_address);
+
+ if (recstate == SLOW_WAIT_FOR_CLOCK) {
+ mm_switch_drive(addr, shift_function, shift_command);
+ }
+
+
+ if (recstate == FAST_WAIT_FOR_CLOCK && addr) {
+ uint8_t command = lookup_command(shift_command);
+ /* Congratulations, we have a valid command */
+ mm_switch_command(addr, command);
}
}
+ address_last = shift_address;
+ function_last = shift_function;
+ command_last = shift_command;
}
+
}
}
+//void __attribute((weak)) mm_switch_drive(uint8_t address, uint8_t function, uint8_t command);
+
ISR(BADISR_vect)
{
while(1) {
{
return;
while(1) {
- setpin(PIN_LED, 1);
+ setpin(PIN_LED, 1);
_delay_ms(30);
setpin(PIN_LED, 0);
_delay_ms(300);
sense_last = MM_SENSE;
if (!sense_last)
return;
-
+
switch(recstate) {
case IDLE:
bitno = 0;