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'); +} |