diff options
| author | VG <vg@devys.org> | 2015-08-26 18:45:01 +0200 | 
|---|---|---|
| committer | VG <vg@devys.org> | 2015-08-26 18:45:01 +0200 | 
| commit | 7346cfaad4d969db060f3c7ae242ea93f4fff5c0 (patch) | |
| tree | 3d3a09a29f783270b8da931e3c879234553ec43f | |
| download | avr-7346cfaad4d969db060f3c7ae242ea93f4fff5c0.tar.gz avr-7346cfaad4d969db060f3c7ae242ea93f4fff5c0.tar.bz2 avr-7346cfaad4d969db060f3c7ae242ea93f4fff5c0.zip  | |
first commitboo-standby-watcher-last-with-amp
| -rw-r--r-- | .gitignore | 4 | ||||
| -rw-r--r-- | atxswitch/Makefile | 35 | ||||
| -rw-r--r-- | atxswitch/main.c | 25 | ||||
| -rw-r--r-- | atxswitch/uart.h | 76 | ||||
| -rw-r--r-- | avr-blinkled-atmega328p/Makefile | 35 | ||||
| -rw-r--r-- | avr-blinkled-atmega328p/main.c | 17 | ||||
| -rw-r--r-- | boo-stanby-watcher/Makefile | 39 | ||||
| -rw-r--r-- | boo-stanby-watcher/main.c | 307 | ||||
| -rw-r--r-- | powerswitch2/Makefile | 39 | ||||
| -rw-r--r-- | powerswitch2/main.c | 39 | ||||
| -rw-r--r-- | readme | 6 | ||||
| -rw-r--r-- | serial/Makefile | 35 | ||||
| -rw-r--r-- | serial/main.c | 25 | ||||
| -rw-r--r-- | serial/uart.h | 76 | ||||
| -rw-r--r-- | softserial.c | 33 | 
15 files changed, 791 insertions, 0 deletions
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 +} @@ -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'); +}  | 
