From 7346cfaad4d969db060f3c7ae242ea93f4fff5c0 Mon Sep 17 00:00:00 2001
From: VG <vg@devys.org>
Date: Wed, 26 Aug 2015 18:45:01 +0200
Subject: first commit

---
 .gitignore                       |   4 +
 atxswitch/Makefile               |  35 +++++
 atxswitch/main.c                 |  25 ++++
 atxswitch/uart.h                 |  76 ++++++++++
 avr-blinkled-atmega328p/Makefile |  35 +++++
 avr-blinkled-atmega328p/main.c   |  17 +++
 boo-stanby-watcher/Makefile      |  39 +++++
 boo-stanby-watcher/main.c        | 307 +++++++++++++++++++++++++++++++++++++++
 powerswitch2/Makefile            |  39 +++++
 powerswitch2/main.c              |  39 +++++
 readme                           |   6 +
 serial/Makefile                  |  35 +++++
 serial/main.c                    |  25 ++++
 serial/uart.h                    |  76 ++++++++++
 softserial.c                     |  33 +++++
 15 files changed, 791 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 atxswitch/Makefile
 create mode 100644 atxswitch/main.c
 create mode 100644 atxswitch/uart.h
 create mode 100644 avr-blinkled-atmega328p/Makefile
 create mode 100644 avr-blinkled-atmega328p/main.c
 create mode 100644 boo-stanby-watcher/Makefile
 create mode 100644 boo-stanby-watcher/main.c
 create mode 100644 powerswitch2/Makefile
 create mode 100644 powerswitch2/main.c
 create mode 100644 readme
 create mode 100644 serial/Makefile
 create mode 100644 serial/main.c
 create mode 100644 serial/uart.h
 create mode 100644 softserial.c

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f46de5a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.pyc
+*.elf
+*.hex
+*.o
diff --git a/atxswitch/Makefile b/atxswitch/Makefile
new file mode 100644
index 0000000..db8a005
--- /dev/null
+++ b/atxswitch/Makefile
@@ -0,0 +1,35 @@
+# settings for arduino nano v3
+DEVICE     = atmega328p
+CLOCK      = 16000000
+PORT=/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A9SBZLHD-if00-port0
+#AVRDUDE=avrdude -V -F -p m328p -c arduino -b 115200 -P$(PORT)
+#AVRDUDE=avrdude -p $(DEVICE) -c arduino -b 115200 -P $(PORT)
+AVRDUDE=avrdude -p $(DEVICE) -c arduino -b 57600 -P $(PORT)
+
+DEFS    = -DF_CPU=$(CLOCK)UL
+LIBS    = -Wl,--relax,--gc-sections,--print-gc-sections,--entry=main
+LIBS = -Wl,--entry=main,--gc-sections,--rela
+CFLAGS  = -Wall -Werror -pedantic -std=c99
+CFLAGS += -Os -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -mmcu=$(DEVICE) $(DEFS)
+#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
+	$(AVRDUDE) -U flash:w:main.hex:i
+
+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/atxswitch/main.c b/atxswitch/main.c
new file mode 100644
index 0000000..2e9ff5c
--- /dev/null
+++ b/atxswitch/main.c
@@ -0,0 +1,25 @@
+#include <avr/io.h>
+#include "uart.h"
+
+int main(void)
+{
+    /* serial */
+    uart_init();
+
+    /* D4 = output and high (=> atx down) */
+    PORTD |= 0x10;
+    DDRD  |= 0x10;
+
+    for (;;)
+    {
+        switch(uart_getchar()) {
+            case '?': break; /* useful for auto documentation */
+            case '0': PORTD |=  0x10; break;
+            case '1': PORTD &= ~0x10; break;
+            case 'T': PORTD ^=  0x10; break;
+        }
+        uart_putchar((PORTD & 0x10) ? '0' : '1');
+    }
+
+    return 0;
+}
diff --git a/atxswitch/uart.h b/atxswitch/uart.h
new file mode 100644
index 0000000..22e0655
--- /dev/null
+++ b/atxswitch/uart.h
@@ -0,0 +1,76 @@
+/* #define F_CPU 16000000UL <= defined in Makefile */
+#define BAUD 9600
+
+/* This file is *highly* inspired from:
+ * http://www.appelsiini.net/2011/simple-usart-with-avr-libc
+ */
+
+#include <util/setbaud.h>
+
+#if 0
+static inline void uart_init()
+{
+    UCSRB |= (1 << RXEN)  | (1 << TXEN);
+    UCSRC |= (1 << UCSZ0) | (1 << UCSZ1);
+#define BAUD 115200
+#include <util/setbaud.h>
+    UBRRH = UBRRH_VALUE;
+    UBRRL = UBRRL_VALUE;
+#if USE_2X
+    UCSRA |= (1 << U2X);
+#else
+    UCSRA &= ~(1 << U2X);
+#endif
+}
+#endif
+
+void uart_init(void)
+{
+    UBRR0H = UBRRH_VALUE;
+    UBRR0L = UBRRL_VALUE;
+
+#if USE_2X
+    UCSR0A |= _BV(U2X0);
+#else
+    UCSR0A &= ~(_BV(U2X0));
+#endif
+
+    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
+    UCSR0B = _BV(RXEN0) | _BV(TXEN0);   /* Enable RX and TX */
+}
+
+void uart_putchar(char c)
+{
+    UDR0 = c;
+    loop_until_bit_is_set(UCSR0A, TXC0); /* Wait until transmission ready. */
+}
+
+char uart_getchar(void)
+{
+    loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
+    return UDR0;
+}
+
+#if 0
+/* alternatives for stream uses */
+void uart_putchar(char c, FILE *stream)
+{
+    if (c == '\n') {
+        uart_putchar('\r', stream);
+    }
+    loop_until_bit_is_set(UCSR0A, UDRE0);
+    UDR0 = c;
+}
+
+char uart_getchar(FILE *stream)
+{
+    loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
+    return UDR0;
+}
+#endif
+
+#if 0
+FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
+FILE uart_input = FDEV_SETUP_STREAM(NULL, uart_getchar, _FDEV_SETUP_READ);
+FILE uart_io FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
+#endif
diff --git a/avr-blinkled-atmega328p/Makefile b/avr-blinkled-atmega328p/Makefile
new file mode 100644
index 0000000..864e2ec
--- /dev/null
+++ b/avr-blinkled-atmega328p/Makefile
@@ -0,0 +1,35 @@
+# settings for arduino uno
+DEVICE     = atmega328p
+CLOCK      = 16000000
+
+# buspirate programmer
+PORT=/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A400XJSH-if00-port0
+AVRDUDE=avrdude -p $(DEVICE) -c buspirate -P $(PORT)
+
+DEFS    = -DF_CPU=$(CLOCK)UL
+LIBS    = -Wl,--relax,--gc-sections,--print-gc-sections,--entry=main
+LIBS = -Wl,--entry=main,--gc-sections,--rela
+CFLAGS  = -Wall -Werror -pedantic -std=c99
+CFLAGS += -Os -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -mmcu=$(DEVICE) $(DEFS)
+#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
+	$(AVRDUDE) -U flash:w:main.hex:i
+
+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/avr-blinkled-atmega328p/main.c b/avr-blinkled-atmega328p/main.c
new file mode 100644
index 0000000..8d9e288
--- /dev/null
+++ b/avr-blinkled-atmega328p/main.c
@@ -0,0 +1,17 @@
+#include <avr/io.h>
+#include <util/delay.h>
+
+int main(void)
+{
+    /* PB4 output */
+    DDRD  |=  _BV(PB4);
+    PORTB &= ~_BV(PB4);
+
+    for (;;)
+    {
+        _delay_ms(1000);
+        PORTB ^= _BV(PB4);
+    }
+
+    return 0;
+}
diff --git a/boo-stanby-watcher/Makefile b/boo-stanby-watcher/Makefile
new file mode 100644
index 0000000..2646d03
--- /dev/null
+++ b/boo-stanby-watcher/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/boo-stanby-watcher/main.c b/boo-stanby-watcher/main.c
new file mode 100644
index 0000000..5c24c1b
--- /dev/null
+++ b/boo-stanby-watcher/main.c
@@ -0,0 +1,307 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+/* Pinout used:
+ *                     -----
+ * reset              - MCU - Vcc2
+ * module reset (PB3) - MCU - (ADC1) Vcc1 mesurement
+ * module set   (PB4) - MCU - not used
+ * GND                - MCU - (PB0) Amp DC control
+ *                     -----
+ */
+
+// assume computer is shutting down if vcc1 is below this value
+static const uint8_t ADC_DOWN_VALUE = 217;
+
+/* times are in tenth of seconds since ISR is triggered every 0.1s~
+ * see init_timer */
+static const uint8_t SLEPT1_TIMEOUT = 10;  /* 1s */
+static const uint8_t SLEPT2_TIMEOUT = 35; /* 3.5s */
+static const uint8_t CAPA_TIMEOUT   = 10; /* 1s   */
+
+static void init_adc()
+{
+  /* this function initialises the ADC
+
+        ADC Notes
+
+        Prescaler
+
+        ADC Prescaler needs to be set so that the ADC input frequency is
+        between 50 - 200kHz.
+
+        Example prescaler values for various frequencies
+
+        Clock   Available prescaler values
+   ---------------------------------------
+         1 MHz   8   (125kHz), 16  (62.5kHz)
+         4 MHz   32  (125kHz), 64  (62.5kHz)
+         8 MHz   64  (125kHz), 128 (62.5kHz)
+        16 MHz   128 (125kHz)
+
+   set prescaler to 128 for mcu running at 8MHz
+  */
+
+  ADMUX =
+            (0 << REFS1) |     // Sets ref. voltage to VCC, bit 1
+            (0 << REFS0) |     // Sets ref. voltage to VCC, bit 0
+            (1 << ADLAR) |     // left shift result
+            (0 << REFS2) |     // Sets ref. voltage to VCC, bit 2
+            (0 << MUX3)  |     // use ADC1 for input, MUX bit 3
+            (0 << MUX2)  |     // use ADC1 for input, MUX bit 2
+            (0 << MUX1)  |     // use ADC1 for input, MUX bit 1
+            (1 << MUX0);       // use ADC1 for input, MUX bit 0
+
+  ADCSRA =
+            (1 << ADEN)  |     // Enable ADC
+            (0 << ADSC)  |     // Do not start conversion
+            (0 << ADATE) |     // Do not enable Auto Trigger
+            (0 << ADIF)  |     // Do not set Interrupt flag
+            (0 << ADIE)  |     // Do not set interrupt enable
+            (1 << ADPS2) |     // set prescaler to 16, bit 2
+            (0 << ADPS1) |     // set prescaler to 16, bit 1
+            (0 << ADPS0);      // set prescaler to 16, bit 0
+}
+
+// Value is between Vcc 3.4V (255) and GND (0).
+static uint8_t read_adc()
+{
+    ADCSRA |= (1 << ADSC);          // start ADC measurement
+    while (ADCSRA & (1 << ADSC));   // wait till conversion complete
+    return ADCH;                    // value is between 0 (=GND) and 255 (=Vcc)
+}
+
+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;
+static volatile uint8_t capa_time;
+
+ISR(TIMER0_COMPA_vect)
+{
+    ++sleep_time;
+    ++capa_time;
+}
+
+static uint8_t get_capa_time(void)
+{
+    return capa_time;
+}
+
+static uint8_t get_sleep_time(void)
+{
+    return sleep_time;
+}
+
+static void reset_capa_time(void)
+{
+    capa_time = 0;
+}
+
+static void reset_sleep_time(void)
+{
+    sleep_time = 0;
+}
+
+static void plug_set()
+{
+    PORTB &= ~(1 << PB3); /* make sure reset line is disabled */
+    PORTB |= (1 << PB4); /* activate plug modules set */
+}
+
+static void plug_unset()
+{
+    PORTB &= ~(1 << PB4); /* deactivate plug modules set */
+}
+
+static void amp_set()
+{
+    PORTB |= (1 << PB0);
+}
+
+static void amp_plug_reset()
+{
+    /* 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();
+    /* deactivate amp dc control and activate module reset */
+    PORTB &= ~(1 << PB0);
+    PORTB |= (1 << PB3);
+}
+
+static void amp_plug_unreset()
+{
+    PORTB &= ~(1 << PB3);
+}
+
+static enum states {
+    ST_1_AMP_PLUG_OFF,
+    ST_2_PLUG_SET,
+    ST_3_PLUG_ON,
+    ST_4_IDLE, /* when plug and amp are on we are in idle state */
+    ST_5_AMP_PLUG_RESET,
+    /* ST_OFF never reached normally :P it only appears in the diagram */
+    ST_MAX
+} current_state = ST_1_AMP_PLUG_OFF;
+
+enum events {
+    EV_1_CAPA_LOADED,
+    EV_2_SLEPT1,
+    EV_3_SLEPT2,
+    EV_4_UNLOADING, /* no more current, capa temp power unloading */
+    EV_MAX
+};
+
+static void s0_e0(void); /* do nothing */
+static void s1_e1(void);
+static void s2_e2(void);
+static void s2_e4(void);
+static void s3_e3(void);
+static void s3_e4(void);
+static void s4_e4(void);
+static void s5_e2(void);
+
+static void (*const state_table [ST_MAX][EV_MAX])(void) = {
+    {s1_e1, s0_e0, s0_e0, s0_e0},
+    {s0_e0, s2_e2, s0_e0, s2_e4},
+    {s0_e0, s0_e0, s3_e3, s3_e4},
+    {s0_e0, s0_e0, s0_e0, s4_e4},
+    {s0_e0, s5_e2, s0_e0, s0_e0},
+};
+
+static void process_event(enum events new_event)
+{
+    state_table[current_state][new_event]();
+}
+
+static void s0_e0(void) {}
+
+static void s1_e1(void) /* amp&plug off: capa loaded */
+{
+    plug_set();
+    reset_sleep_time();
+    current_state = ST_2_PLUG_SET;
+}
+
+static void s2_e2(void) /* plug set: slept1 */
+{
+    plug_unset();
+    reset_sleep_time();
+    current_state = ST_3_PLUG_ON;
+}
+
+static void s2_e4(void) /* plug set: unloading */
+{
+    amp_plug_reset();
+    reset_sleep_time();
+    current_state = ST_5_AMP_PLUG_RESET;
+}
+
+static void s3_e3(void) /* plug on: slept2 */
+{
+    amp_set();
+    current_state = ST_4_IDLE;
+}
+
+static void s3_e4(void) /* plug on: unloading */
+{
+    amp_plug_reset();
+    reset_sleep_time();
+    current_state = ST_5_AMP_PLUG_RESET;
+}
+
+static void s4_e4(void) /* idle: unloading */
+{
+    amp_plug_reset();
+    reset_sleep_time();
+    current_state = ST_5_AMP_PLUG_RESET;
+}
+
+static void s5_e2(void) /* amp&plug reset: slept1 */
+{
+    amp_plug_unreset();
+    current_state = ST_1_AMP_PLUG_OFF;
+}
+
+int main()
+{
+    uint8_t adcval;
+
+    cli();
+
+    init_adc();
+    init_timer();
+
+    // digital output
+    DDRB |=
+        (1 << PB0) |    // Amp DC control
+        (1 << PB3) |    // module reset
+        (1 << PB4);     // module set
+    PORTB = 0; // outputs set to low and input not set to internal pull-up
+
+    // first ADC conversion may be inaccurate
+    // atmel advises to discard the result
+    adcval = read_adc();
+
+    sei();
+
+    for (;;) { /* main loop */
+
+        adcval = read_adc();
+
+        if (get_capa_time() >= CAPA_TIMEOUT) {
+            process_event(EV_1_CAPA_LOADED);
+        }
+
+        if (get_sleep_time() >= SLEPT1_TIMEOUT) {
+            process_event(EV_2_SLEPT1);
+        }
+
+        if (get_sleep_time() >= SLEPT2_TIMEOUT) {
+            process_event(EV_3_SLEPT2);
+        }
+
+        if (adcval <= ADC_DOWN_VALUE) {
+            reset_capa_time();
+            process_event(EV_4_UNLOADING);
+        }
+    }
+
+    return 0;
+}
diff --git a/powerswitch2/Makefile b/powerswitch2/Makefile
new file mode 100644
index 0000000..104f084
--- /dev/null
+++ b/powerswitch2/Makefile
@@ -0,0 +1,39 @@
+DEVICE     = attiny2313
+CLOCK      = 8000000
+FUSES      = -U lfuse:w:0xe4:m -U hfuse:w:0xd9:m
+
+PROGRAMMER  =-c stk500v2
+PROGRAMMER +=-P /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A800dAli-if00-port0
+# in ms should be at least 4 times less than clock speed
+SPEED      = 4 # for default 1Mhz clock
+#SPEED      = 0.34 # for 12Mhz clock
+DEFS    = -DF_CPU=$(CLOCK)UL
+LIBS    = -Wl,--relax,--gc-sections,--print-gc-sections,--entry=main
+LIBS = -Wl,--entry=main,--gc-sections,--rela
+CFLAGS  = -Wall -Werror -pedantic -std=c99
+CFLAGS += -Os -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -mmcu=$(DEVICE) $(DEFS)
+#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
+	avrdude $(PROGRAMMER) -p $(DEVICE) -B $(SPEED) -U flash:w:main.hex:i
+
+fuse:
+	avrdude $(PROGRAMMER) -p $(DEVICE) -B $(SPEED) $(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/powerswitch2/main.c b/powerswitch2/main.c
new file mode 100644
index 0000000..63e5d5c
--- /dev/null
+++ b/powerswitch2/main.c
@@ -0,0 +1,39 @@
+#include <avr/io.h>
+#include <util/delay.h>
+
+static inline void uart_init();
+int main()
+{
+    /* serial */
+    uart_init();
+
+    /* data input */
+    PORTB &= ~0x0F;
+    DDRB  |=  0x0F;
+
+    for (;;)
+    {
+        while ((UCSRA & (1 << RXC)) == 0);
+        PORTB ^= UDR & 0x0F;
+
+        while ((UCSRA & (1 << UDRE)) == 0);
+        UDR = PORTB & 0x0F;
+    }
+
+    return 0;
+}
+
+static inline void uart_init()
+{
+    UCSRB |= (1 << RXEN)  | (1 << TXEN);
+    UCSRC |= (1 << UCSZ0) | (1 << UCSZ1);
+#define BAUD 38400
+#include <util/setbaud.h>
+    UBRRH = UBRRH_VALUE;
+    UBRRL = UBRRL_VALUE;
+#if USE_2X
+    UCSRA |= (1 << U2X);
+#else
+    UCSRA &= ~(1 << U2X);
+#endif
+}
diff --git a/readme b/readme
new file mode 100644
index 0000000..5551cd5
--- /dev/null
+++ b/readme
@@ -0,0 +1,6 @@
+This is a repository containing some basic avr examples.
+
+Can be useful for quick debuging, or to validate a component or module works.
+
+Sometimes I put working avr code for modules I develop, not big enough to have
+its own repository.
diff --git a/serial/Makefile b/serial/Makefile
new file mode 100644
index 0000000..98f1efc
--- /dev/null
+++ b/serial/Makefile
@@ -0,0 +1,35 @@
+# settings for arduino 
+DEVICE     = atmega328p
+CLOCK      = 16000000
+PORT=/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A400XJSH-if00-port0
+#AVRDUDE=avrdude -V -F -p m328p -c arduino -b 115200 -P$(PORT)
+#AVRDUDE=avrdude -p $(DEVICE) -c arduino -b 115200 -P $(PORT)
+AVRDUDE=avrdude -p $(DEVICE) -c arduino -b 57600 -P $(PORT)
+
+DEFS    = -DF_CPU=$(CLOCK)UL
+LIBS    = -Wl,--relax,--gc-sections,--print-gc-sections,--entry=main
+LIBS = -Wl,--entry=main,--gc-sections,--rela
+CFLAGS  = -Wall -Werror -pedantic -std=c99
+CFLAGS += -Os -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -mmcu=$(DEVICE) $(DEFS)
+#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
+	$(AVRDUDE) -U flash:w:main.hex:i
+
+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/serial/main.c b/serial/main.c
new file mode 100644
index 0000000..2e9ff5c
--- /dev/null
+++ b/serial/main.c
@@ -0,0 +1,25 @@
+#include <avr/io.h>
+#include "uart.h"
+
+int main(void)
+{
+    /* serial */
+    uart_init();
+
+    /* D4 = output and high (=> atx down) */
+    PORTD |= 0x10;
+    DDRD  |= 0x10;
+
+    for (;;)
+    {
+        switch(uart_getchar()) {
+            case '?': break; /* useful for auto documentation */
+            case '0': PORTD |=  0x10; break;
+            case '1': PORTD &= ~0x10; break;
+            case 'T': PORTD ^=  0x10; break;
+        }
+        uart_putchar((PORTD & 0x10) ? '0' : '1');
+    }
+
+    return 0;
+}
diff --git a/serial/uart.h b/serial/uart.h
new file mode 100644
index 0000000..22e0655
--- /dev/null
+++ b/serial/uart.h
@@ -0,0 +1,76 @@
+/* #define F_CPU 16000000UL <= defined in Makefile */
+#define BAUD 9600
+
+/* This file is *highly* inspired from:
+ * http://www.appelsiini.net/2011/simple-usart-with-avr-libc
+ */
+
+#include <util/setbaud.h>
+
+#if 0
+static inline void uart_init()
+{
+    UCSRB |= (1 << RXEN)  | (1 << TXEN);
+    UCSRC |= (1 << UCSZ0) | (1 << UCSZ1);
+#define BAUD 115200
+#include <util/setbaud.h>
+    UBRRH = UBRRH_VALUE;
+    UBRRL = UBRRL_VALUE;
+#if USE_2X
+    UCSRA |= (1 << U2X);
+#else
+    UCSRA &= ~(1 << U2X);
+#endif
+}
+#endif
+
+void uart_init(void)
+{
+    UBRR0H = UBRRH_VALUE;
+    UBRR0L = UBRRL_VALUE;
+
+#if USE_2X
+    UCSR0A |= _BV(U2X0);
+#else
+    UCSR0A &= ~(_BV(U2X0));
+#endif
+
+    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
+    UCSR0B = _BV(RXEN0) | _BV(TXEN0);   /* Enable RX and TX */
+}
+
+void uart_putchar(char c)
+{
+    UDR0 = c;
+    loop_until_bit_is_set(UCSR0A, TXC0); /* Wait until transmission ready. */
+}
+
+char uart_getchar(void)
+{
+    loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
+    return UDR0;
+}
+
+#if 0
+/* alternatives for stream uses */
+void uart_putchar(char c, FILE *stream)
+{
+    if (c == '\n') {
+        uart_putchar('\r', stream);
+    }
+    loop_until_bit_is_set(UCSR0A, UDRE0);
+    UDR0 = c;
+}
+
+char uart_getchar(FILE *stream)
+{
+    loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
+    return UDR0;
+}
+#endif
+
+#if 0
+FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
+FILE uart_input = FDEV_SETUP_STREAM(NULL, uart_getchar, _FDEV_SETUP_READ);
+FILE uart_io FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
+#endif
diff --git a/softserial.c b/softserial.c
new file mode 100644
index 0000000..cbec672
--- /dev/null
+++ b/softserial.c
@@ -0,0 +1,33 @@
+
+#define baud 9600
+#define serial_bit_delay 1000000/baud
+#define SERIAL_LOW() PORTB &= ~_BV(PB4)
+#define SERIAL_HIGH() PORTB |= _BV(PB4)
+
+// write out a byte as software emulated Uart
+void serial_putchar(uint8_t byte)
+{
+    uint8_t mask;
+    SERIAL_LOW(); // signal start bit
+    _delay_us(serial_bit_delay);
+    for (mask = 0x01; mask; mask <<= 1) {
+        if (byte & mask) { // choose bit
+            SERIAL_HIGH(); // send 1
+        } else {
+            SERIAL_LOW(); // send 0
+        }
+        _delay_us(serial_bit_delay);
+    }
+    SERIAL_HIGH();  //signal end bit
+    _delay_us(serial_bit_delay);
+}
+
+void serial_puts(const char* str)
+{
+    while (*str) {
+        serial_putchar((uint8_t)*str);
+        ++str;
+    }
+    serial_putchar('\r');
+    serial_putchar('\n');
+}
-- 
cgit v1.2.3