diff options
author | VG <vg@devys.org> | 2015-10-05 20:56:15 +0200 |
---|---|---|
committer | VG <vg@devys.org> | 2015-10-05 20:56:15 +0200 |
commit | 21a6c53bfb10d51a72f5b3135c65b8fd7440ac28 (patch) | |
tree | 268dde8e1005769224213322978bcf4b8eb7078a | |
parent | 1215068c8ff39cb10d5d5256e7693e83be1834e3 (diff) | |
download | avr-21a6c53bfb10d51a72f5b3135c65b8fd7440ac28.tar.gz avr-21a6c53bfb10d51a72f5b3135c65b8fd7440ac28.tar.bz2 avr-21a6c53bfb10d51a72f5b3135c65b8fd7440ac28.zip |
add synology auto-poweron manager
-rw-r--r-- | synology-autopoweron/Makefile | 39 | ||||
-rw-r--r-- | synology-autopoweron/main.c | 118 |
2 files changed, 157 insertions, 0 deletions
diff --git a/synology-autopoweron/Makefile b/synology-autopoweron/Makefile new file mode 100644 index 0000000..2646d03 --- /dev/null +++ b/synology-autopoweron/Makefile @@ -0,0 +1,39 @@ +DEVICE = attiny25 +CLOCK = 1000000 +FUSES = -U lfuse:w:0x62:m -U hfuse:w:0xdd:m + +PROGRAMMER = avrdude +PROGRAMMER += -c buspirate +PROGRAMMER += -P /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A400XJSH-if00-port0 +PROGRAMMER += -p $(DEVICE) -B 4 + +DEFS = -DF_CPU=$(CLOCK)UL +CFLAGS = -Wall -Werror -pedantic -std=c99 +CFLAGS += -O2 -funsigned-bitfields -fpack-struct -fshort-enums +CFLAGS += -mmcu=$(DEVICE) $(DEFS) +#LIBS = -Wl,--relax,--gc-sections,--print-gc-sections,--entry=main +#LIBS = -Wl,--entry=main,--gc-sections,--rela +#LDFLAGS = $(LIBS) + +all: main.hex size + +main.hex: main.c + avr-gcc -o main.elf $? $(CFLAGS) $(LDFLAGS) + avr-objcopy -j .text -j .data -O ihex main.elf main.hex + +f: flash +flash: all + $(PROGRAMMER) -U flash:w:main.hex:i + +fuse: + $(PROGRAMMER) $(FUSES) + +clean: + rm -f *.o *.elf *.hex + +size: + avr-size --mcu=$(DEVICE) -t -A main.elf + avr-size --mcu=$(DEVICE) -C main.elf + avr-nm --size-sort main.elf + + diff --git a/synology-autopoweron/main.c b/synology-autopoweron/main.c new file mode 100644 index 0000000..698a887 --- /dev/null +++ b/synology-autopoweron/main.c @@ -0,0 +1,118 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/power.h> + +/* Pinout used: + * ----- + * !reset - MCU - Vcc + * NA - MCU - NA + * NA - MCU - NA + * GND - MCU - (PB0) powerbutton + * ----- + */ + +static const uint8_t SLEPT_TIMEOUT = 25; /* ~2.5s */ + +static void init_timer() +{ + /* timer_resolution = 1 / (clock_speed / prescaler) + * timer_resolution = 1 / (10**6 / 1024) + * + * in ctc mode, target counts: + * + * timer_counts = (target_time / timer_resolution) - 1 + * timer_counts = (0.1 / (1/(10**6/1024))) - 1 + * timer_counts = 96.65625000000001 =~ 97 + * + * Why did we add the extra +1 to our number of timer counts? In CTC mode, + * when the timer matches our desired count it will reset itself to zero. + * This takes one clock cycle to perform, so we need to factor that into + * our calculations. + * + * VG notes: more simply 0 to 97 = 98 values = 98 cycles. + * + * trigger_time = (97+1) * (1/(10**6 / 1024)) =~ 0.100352s + * + * WGM0[2:0] = 010 = CTC + */ + TCCR0A = + (1 << WGM01) | // CTC + (0 << WGM00); // CTC + TCCR0B = + (0 << WGM02) | // CTC + (1 << CS02) | // CS0[2:0] = 101 => prescaler clk/1024 + (0 << CS01) | // CS0[2:0] = 101 => prescaler clk/1024 + (1 << CS00); // CS0[2:0] = 101 => prescaler clk/1024 + OCR0A = 97; + TIMSK = + (1 << OCIE0A) | // enable CTC interrupt for compare match 0A + (0 << OCIE0B) | // disable CTC interrupt for compare match 0B + (0 << TOIE0); // disable interrupt for timer0 overflow + +} + +static volatile uint8_t sleep_time; + +ISR(TIMER0_COMPA_vect) +{ + ++sleep_time; +} + +static uint8_t get_sleep_time(void) +{ + return sleep_time; +} + +static void reset_sleep_time(void) +{ + sleep_time = 0; +} + +static void button_pushed() +{ + PORTB &= ~(1 << PB3); /* make sure reset line is disabled */ + PORTB |= (1 << PB4); /* activate plug modules set */ +} + +static void button_normal() +{ + /* be sure set line is not active before doing a reset else both coil will + * be energized at the same time and thus the behaviour may be + * unpredictable. */ + plug_unset(); + /* activate module reset */ + PORTB |= (1 << PB3); +} + +int main() +{ + cli(); + init_timer(); + sei(); + + // Normally a loop is not required but if somehow the mcu woke up from its + // sleep state this ensure we can do the operation again. + for (;;) { + reset_sleep_time(); + + PORTB = 0; // outputs set to low and input not set to internal pull-up + + // digital output, pull-down for a time then go to default PB0 = Hi-Z + DDRB |= (1 << PB0); + while (get_sleep_time() <= SLEPT_TIMEOUT); + DDRB &= ~(1 << PB0); + + /* set low power mode */ + power_all_disable(); // disable all peripherals + set_sleep_mode(<mode>); // sleep mode + sleep_enable(); // set register to enable sleep + sleep_bod_disable(); // disable bod to consume even less + //sei(); // normally set sei to ensure wakeup but I do + // not want to wake up appart from a power + // reset + sleep_cpu(); // put cpu to sleep = low power mode now + sleep_disable(); // clear register (if somehow mcu woke up) + } + + return 0; +} |