diff --git a/code/.clang_complete b/code/.clang_complete new file mode 100644 index 0000000..21edecc --- /dev/null +++ b/code/.clang_complete @@ -0,0 +1,3 @@ +-D__AVR_ATxmega32A4__ +-I/usr/lib/avr/include +-I./inc diff --git a/code/Makefile b/code/Makefile new file mode 100644 index 0000000..54e99df --- /dev/null +++ b/code/Makefile @@ -0,0 +1,154 @@ +MCU = atxmega32a4 +TARGET = main +AVRDUDE_PROGRAMMER = atmelice_pdi +FCPU=2000000UL + +BUILDDIR=build + +OPT = s +SRC = $(shell find src -name '*.c') +#SRC = main.c + +FORMAT = ihex + +# List any extra directories to look for include files here. +# Each directory must be seperated by a space. +EXTRAINCDIRS = inc + +#### Flags #### +CFLAGS = -mmcu=$(MCU) -I. \ +-g -ggdb -O$(OPT) \ +-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \ +-Wall -Wstrict-prototypes \ +-Wa,-adhlns=$(<:src/%.c=$(BUILDDIR)/%.lst) \ +-DF_CPU=$(FCPU)\ +$(patsubst %,-I%,$(EXTRAINCDIRS))\ +-std=gnu99 \ +-fno-builtin + +LDFLAGS = -Wl,-Map=$(BUILDDIR)/$(TARGET).map,--cref +# Minimalistic printf version +#LDFLAGS += -Wl,-u,vfprintf -lprintf_min + +# Floating point printf version (requires -lm below) +#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt + +# -lm = math library +LDFLAGS += -lm +#LDFLAGS += -nostdlib + +AVRDUDE_FLAGS = -p $(MCU) -c $(AVRDUDE_PROGRAMMER) -U flash:w:$(BUILDDIR)/$(TARGET).hex + +#### Define programs and commands. #### +CC = avr-gcc + +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +SIZE = avr-size +AVRDUDE = avrdude + + +REMOVE = rm -f +COPY = cp + +# Define all object files. +OBJ = $(SRC:src/%.c=$(BUILDDIR)/%.o) + +# Define all listing files. +LST = $(SRC:src/%.c=$(BUILDDIR)/%.lst) + +# Default target: make program! +all: $(TARGET).elf +# $(BUILDDIR)/$(TARGET).lss $(BUILDDIR)/$(TARGET).sym +# $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + +# Program the device. +program: $(BUILDDIR)/$(TARGET).hex $(BUILDDIR)/$(TARGET).eep + $(AVRDUDE) $(AVRDUDE_FLAGS) + + +# Create final output files (.hex, .eep) from ELF output file. +$(BUILDDIR)/%.hex: %.elf + @echo + @echo "creating ihex" + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +$(BUILDDIR)/%.eep: %.elf + @echo + @echo "eeprom" + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + +# Create extended listing file from ELF output file. +$(BUILDDIR)/%.lss: %.elf + @echo + @echo "listing" + $(OBJDUMP) -h -S $< > $@ + +# Create a symbol table from ELF output file. +$(BUILDDIR)/%.sym: %.elf + @echo + @echo "symbol table" + avr-nm -n $< > $@ + + + +# Link: create ELF output file from object files. +#.SECONDARY : $(BUILDDIR)/$(TARGET).elf +#.PRECIOUS : $(OBJ) +$(TARGET).elf: $(OBJ) + @echo + @echo "linking: " $(OBJ) + mkdir -p build + $(CC) $(CFLAGS) $(OBJ) --output $@ $(LDFLAGS) + + +# Compile: create object files from C source files. +$(BUILDDIR)/%.o : src/%.c + @echo + @echo "compiling" $< + mkdir -p build + $(CC) -c $(CFLAGS) $< -o $@ + + +# Target: clean project. +clean: + @echo + @echo "cleaning" + $(REMOVE) $(BUILDDIR)/$(TARGET).hex + $(REMOVE) $(BUILDDIR)/$(TARGET).eep + $(REMOVE) $(BUILDDIR)/$(TARGET).obj + $(REMOVE) $(BUILDDIR)/$(TARGET).cof + $(REMOVE) $(TARGET).elf + $(REMOVE) $(BUILDDIR)/$(TARGET).map + $(REMOVE) $(BUILDDIR)/$(TARGET).obj + $(REMOVE) $(BUILDDIR)/$(TARGET).a90 + $(REMOVE) $(BUILDDIR)/$(TARGET).sym + $(REMOVE) $(BUILDDIR)/$(TARGET).lnk + $(REMOVE) $(BUILDDIR)/$(TARGET).lss + $(REMOVE) $(OBJ) + $(REMOVE) $(LST) + $(REMOVE) $(SRC:src/%.c=$(BUILDDIR)/%.s) + $(REMOVE) $(SRC:src/%.c=$(BUILDDIR)/%.d) + $(REMOVE) $(BUILDDIR)/*~ + +# Automatically generate C source code dependencies. +# (Code originally taken from the GNU make user manual and modified +# (See README.txt Credits).) +# +# Note that this will work with sh (bash) and sed that is shipped with WinAVR +# (see the SHELL variable defined above). +# This may not work with other shells or other seds. +# +$(BUILDDIR)/%.d: %.c + set -e; $(CC) -MM $(CFLAGS) $< \ + | sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \ + [ -s $@ ] || rm -f $@ + + +# Remove the '-' if you want to see the dependency files generated. +-include $(SRC:.c=.d) + +# Listing of phony targets. +.PHONY : all clean program + diff --git a/code/inc/fifo.h b/code/inc/fifo.h new file mode 100644 index 0000000..e1ad9d1 --- /dev/null +++ b/code/inc/fifo.h @@ -0,0 +1,20 @@ +#ifndef _FIFO_H_ +#define _FIFO_H_ + +#include + +#define FIFO_FAIL 0 +#define FIFO_SUCCESS 1 + +#define FIFO_SIZE 128 + +typedef struct { + uint8_t data[FIFO_SIZE]; + uint8_t read; // zeigt auf das Feld mit dem ältesten Inhalt + uint8_t write; // zeigt immer auf leeres Feld +} Fifo_t; + +uint8_t fifo_push(Fifo_t * fifo, uint8_t byte); +uint8_t fifo_pop(Fifo_t * fifo, uint8_t *pByte); + +#endif diff --git a/code/inc/uart.h b/code/inc/uart.h new file mode 100644 index 0000000..5d8987c --- /dev/null +++ b/code/inc/uart.h @@ -0,0 +1,15 @@ +#ifndef _UART_H_ +#define _UART_H_ + +#include +#include "fifo.h" + +extern Fifo_t uart0_rx_buffer; +extern Fifo_t uart0_tx_buffer; + + +void init_uart(void); +//void putchar(char c); +char get_uart0_char(void); + +#endif diff --git a/code/inc/util.h b/code/inc/util.h new file mode 100644 index 0000000..a39399b --- /dev/null +++ b/code/inc/util.h @@ -0,0 +1,12 @@ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +void delay(int ms); +static void printchar(char **str, int c); +static int prints(char **out, const char *string, int width, int pad); +static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase); +static int print(char **out, int *varg); +int printf(const char *format, ...); +int sprintf(char *out, const char *format, ...); + +#endif diff --git a/code/src/fifo.c b/code/src/fifo.c new file mode 100644 index 0000000..d9d9505 --- /dev/null +++ b/code/src/fifo.c @@ -0,0 +1,40 @@ +#include "fifo.h" +#include "uart.h" + +uint8_t fifo_push(Fifo_t * fifo, uint8_t byte) +{ + //if (fifo.write >= FIFO_SIZE) + // fifo.write = 0; // erhöht sicherheit + + + if ( ( fifo->write + 1 == fifo->read ) || + ( fifo->read == 0 && fifo->write + 1 == FIFO_SIZE ) ) + return FIFO_FAIL; // voll + + fifo->data[fifo->write] = byte; + + fifo->write++; + if (fifo->write >= FIFO_SIZE) + fifo->write = 0; + + return FIFO_SUCCESS; +} + +uint8_t fifo_pop(Fifo_t * fifo, uint8_t *pByte) +{ + if (fifo->read == fifo->write){ + return FIFO_FAIL; + } + + *pByte = fifo->data[fifo->read]; + + fifo->read++; + if (fifo->read >= FIFO_SIZE) + fifo->read = 0; + + return FIFO_SUCCESS; +} + +uint8_t fifo_peek(Fifo_t * fifo){ + return fifo->data[fifo->read]; +} diff --git a/code/src/main.c b/code/src/main.c new file mode 100644 index 0000000..29f7756 --- /dev/null +++ b/code/src/main.c @@ -0,0 +1,102 @@ +#include +#include +#include + +#include +#include +#include + +#include "uart.h" +#include "fifo.h" +#include "util.h" + +void init_clk(void) +{ + + // ========= System Clock configuration ========= + // Set to external 16Mhz crystal, using the PLL at *2 + // set it to be a 12-16Mhz crystal with a slow start-up time. + OSC.XOSCCTRL = OSC_FRQRANGE_2TO9_gc | OSC_XOSCSEL_XTAL_16KCLK_gc ; + OSC.CTRL |= OSC_XOSCEN_bm ; // enable it + while( (OSC.STATUS & OSC_XOSCRDY_bm) == 0 ){} // wait until it's stable + + // The external crystal is now running and stable. + // (Note that it's not yet selected as the clock source) + // Now configure the PLL to be eXternal oscillator * 2 + OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 2 ; + + // now enable the PLL... + OSC.CTRL |= OSC_PLLEN_bm ; // enable the PLL... + while( (OSC.STATUS & OSC_PLLRDY_bm) == 0 ){} // wait until it's stable + + // And now, *finally*, we can switch from the internal 2Mhz clock to the PLL + CCP = CCP_IOREG_gc; // protected write follows + CLK.CTRL = CLK_SCLKSEL_PLL_gc; // The System clock is now PLL (16Mhz * 2) + // ============================================== +} + +void adc_init(void){ + ADCA.CTRLB = 0x00; + ADCA.REFCTRL = ADC_REFSEL_INT1V_gc; + ADCA.PRESCALER = ADC_PRESCALER_DIV512_gc; + + uint8_t CalibrationByteL; + uint8_t CalibrationByteH; + NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc; + CalibrationByteL = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0)); + CalibrationByteH = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1)); + NVM_CMD = NVM_CMD_NO_OPERATION_gc; + ADCA.CALL = CalibrationByteL; + ADCA.CALH = CalibrationByteH; + + ADCA.CTRLA = ADC_ENABLE_bm; + + ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; + ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN1_gc; +// +// ADCA.CH1.CTRL = ADC_CH_INPUTMODE1_bm; +// ADCA.CH1.MUXCTRL = ADC_CH_MUXNEG_PIN1_gc; +// +} + +uint16_t adc_read(void){ + ADCA.CH0.CTRL |= ADC_CH_START_bm; + while(!(ADCA.CH0.INTFLAGS & ADC_CH_CHIF_bm)); + ADCA.CH0.INTFLAGS = ADC_CH_CHIF_bm; + return ADCA.CH0.RES; +} + +uint16_t adc1_read(void){ + ADCA.CH1.CTRL |= ADC_CH_START_bm; + while(!(ADCA.CH1.INTFLAGS & ADC_CH_CHIF_bm)); + ADCA.CH1.INTFLAGS = ADC_CH_CHIF_bm; + return ADCA.CH1.RES; +} + +int main (void) +{ + init_clk(); + init_uart(); + + adc_init(); + + sei(); + PMIC_CTRL = PMIC_LOLVLEN_bm; + PORTA.DIR = 0; + + uint32_t val; + //uint32_t val1; + + printf("moin!\r\n"); + + while(1) + { + val = adc_read(); + val = val * 1000 / 4096; + printf("val: %03dmV\r\n", val); + + //printf("val1: %03d\r\n", val1); + printf("\r\n"); + delay(1000); + } +} diff --git a/code/src/tags b/code/src/tags new file mode 100644 index 0000000..eb77031 --- /dev/null +++ b/code/src/tags @@ -0,0 +1,32 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/ +!_TAG_PROGRAM_AUTHOR Universal Ctags Team // +!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/ +!_TAG_PROGRAM_URL https://ctags.io/ /official site/ +!_TAG_PROGRAM_VERSION 0.0.0 // +ISR uart.c /^ISR(USARTD0_DRE_vect){$/;" f +ISR uart.c /^ISR(USARTD0_RXC_vect)$/;" f +PAD_RIGHT util.c /^#define PAD_RIGHT /;" d file: +PAD_ZERO util.c /^#define PAD_ZERO /;" d file: +PRINT_BUF_LEN util.c /^#define PRINT_BUF_LEN /;" d file: +bscale uart.c /^const int8_t bscale = 0;$/;" v typeref:typename:const int8_t +bsel uart.c /^const uint16_t bsel = 0;$/;" v typeref:typename:const uint16_t +delay util.c /^void delay(int ms){$/;" f typeref:typename:void +fifo_peek fifo.c /^uint8_t fifo_peek(Fifo_t * fifo){$/;" f typeref:typename:uint8_t +fifo_pop fifo.c /^uint8_t fifo_pop(Fifo_t * fifo, uint8_t *pByte)$/;" f typeref:typename:uint8_t +fifo_push fifo.c /^uint8_t fifo_push(Fifo_t * fifo, uint8_t byte)$/;" f typeref:typename:uint8_t +get_uart0_char uart.c /^char get_uart0_char(void)$/;" f typeref:typename:char +init_clk main.c /^void init_clk(void)$/;" f typeref:typename:void +init_uart uart.c /^void init_uart(void){$/;" f typeref:typename:void +main main.c /^int main (void)$/;" f typeref:typename:int +print util.c /^static int print(char **out, int *varg)$/;" f typeref:typename:int file: +printchar util.c /^static void printchar(char **str, int c)$/;" f typeref:typename:void file: +printf util.c /^int printf(const char *format, ...)$/;" f typeref:typename:int +printi util.c /^static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)$/;" f typeref:typename:int file: +prints util.c /^static int prints(char **out, const char *string, int width, int pad)$/;" f typeref:typename:int file: +putchar uart.c /^void putchar(char c)$/;" f typeref:typename:void +puts uart.c /^void puts(char * s){$/;" f typeref:typename:void +sprintf util.c /^int sprintf(char *out, const char *format, ...)$/;" f typeref:typename:int +uart0_rx_buffer uart.c /^Fifo_t uart0_rx_buffer = {{}, 0, 0};$/;" v typeref:typename:Fifo_t +uart0_tx_buffer uart.c /^Fifo_t uart0_tx_buffer = {{}, 0, 0};$/;" v typeref:typename:Fifo_t diff --git a/code/src/uart.c b/code/src/uart.c new file mode 100644 index 0000000..6e96149 --- /dev/null +++ b/code/src/uart.c @@ -0,0 +1,69 @@ +#include +#include "uart.h" +#include "util.h" +#include "fifo.h" + +Fifo_t uart0_rx_buffer = {{}, 0, 0}; +Fifo_t uart0_tx_buffer = {{}, 0, 0}; + +const uint16_t bsel = 13; +const int8_t bscale = 0; + +void init_uart(void){ + USARTD0_CTRLC= USART_CHSIZE0_bm | USART_CHSIZE1_bm; + //USARTD0_BAUDCTRLB = 0; + //USARTD0_BAUDCTRLA = 0; + USARTD0.BAUDCTRLA = bsel; + USARTD0.BAUDCTRLB = 0 | (bsel >> 8) | (bscale << USART_BSCALE0_bp); + USARTD0_CTRLB = USART_TXEN_bm | USART_RXEN_bm; + + USARTD0_CTRLA=USART_RXCINTLVL0_bm; + + PORTD_OUTSET = PIN3_bm; + PORTD_DIRSET = PIN3_bm; + PORTD_OUTCLR = PIN2_bm; + PORTD_DIRCLR = PIN2_bm; +} + +void putchar(char c) +{ + fifo_push(&uart0_tx_buffer, c); + USARTD0_CTRLA |= USART_DREINTLVL_LO_gc; +} + +void puts(char * s){ + while (*s) { + putchar(*s++); + } +} + +char get_uart0_char(void) +{ + while(1){ + char buffer; + + while( !(USARTD0_STATUS & USART_RXCIF_bm) ); + buffer=USARTD0_DATA; + if ((USARTD0_STATUS & (USART_FERR_bm | USART_PERR_bm | USART_BUFOVF_bm))==0) + return buffer; + } +} + +ISR(USARTD0_RXC_vect) +{ + uint8_t tmp = get_uart0_char(); + putchar(tmp); + if(( tmp == 0x0D || tmp == 0x0A)) + printf("wurst\n\r"); + else + fifo_push(&uart0_rx_buffer, tmp); +} + +ISR(USARTD0_DRE_vect){ + uint8_t tmp; + if(fifo_pop(&uart0_tx_buffer, &tmp) == FIFO_SUCCESS){ + USARTD0_DATA = tmp; + } else { + USARTD0_CTRLA &= ~USART_DREINTLVL_LO_gc; + } +} diff --git a/code/src/util.c b/code/src/util.c new file mode 100644 index 0000000..21100c2 --- /dev/null +++ b/code/src/util.c @@ -0,0 +1,199 @@ +void delay(int ms){ + for(int i=0;i 0) { + register int len = 0; + register const char *ptr; + for (ptr = string; *ptr; ++ptr) ++len; + if (len >= width) width = 0; + else width -= len; + if (pad & PAD_ZERO) padchar = '0'; + } + if (!(pad & PAD_RIGHT)) { + for ( ; width > 0; --width) { + printchar (out, padchar); + ++pc; + } + } + for ( ; *string ; ++string) { + printchar (out, *string); + ++pc; + } + for ( ; width > 0; --width) { + printchar (out, padchar); + ++pc; + } + + return pc; +} + +/* the following should be enough for 32 bit int */ +#define PRINT_BUF_LEN 12 + +static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase) +{ + char print_buf[PRINT_BUF_LEN]; + register char *s; + register int t, neg = 0, pc = 0; + register unsigned int u = i; + + if (i == 0) { + print_buf[0] = '0'; + print_buf[1] = '\0'; + return prints (out, print_buf, width, pad); + } + + if (sg && b == 10 && i < 0) { + neg = 1; + u = -i; + } + + s = print_buf + PRINT_BUF_LEN-1; + *s = '\0'; + + while (u) { + t = u % b; + if( t >= 10 ) + t += letbase - '0' - 10; + *--s = t + '0'; + u /= b; + } + + if (neg) { + if( width && (pad & PAD_ZERO) ) { + printchar (out, '-'); + ++pc; + --width; + } + else { + *--s = '-'; + } + } + + return pc + prints (out, s, width, pad); +} + +static int print(char **out, int *varg) +{ + register int width, pad; + register int pc = 0; + register char *format = (char *)(*varg++); + char scr[2]; + + for (; *format != 0; ++format) { + if (*format == '%') { + ++format; + width = pad = 0; + if (*format == '\0') break; + if (*format == '%') goto out; + if (*format == '-') { + ++format; + pad = PAD_RIGHT; + } + while (*format == '0') { + ++format; + pad |= PAD_ZERO; + } + for ( ; *format >= '0' && *format <= '9'; ++format) { + width *= 10; + width += *format - '0'; + } + if( *format == 's' ) { + register char *s = *((char **)varg++); + pc += prints (out, s?s:"(null)", width, pad); + continue; + } + if( *format == 'd' ) { + pc += printi (out, *varg++, 10, 1, width, pad, 'a'); + continue; + } + if( *format == 'x' ) { + pc += printi (out, *varg++, 16, 0, width, pad, 'a'); + continue; + } + if( *format == 'X' ) { + pc += printi (out, *varg++, 16, 0, width, pad, 'A'); + continue; + } + if( *format == 'u' ) { + pc += printi (out, *varg++, 10, 0, width, pad, 'a'); + continue; + } + if( *format == 'c' ) { + /* char are converted to int then pushed on the stack */ + scr[0] = *varg++; + scr[1] = '\0'; + pc += prints (out, scr, width, pad); + continue; + } + } + else { + out: + printchar (out, *format); + ++pc; + } + } + if (out) **out = '\0'; + return pc; +} + +/* assuming sizeof(void *) == sizeof(int) */ + +int printf(const char *format, ...) +{ + register int *varg = (int *)(&format); + return print(0, varg); +} + +int sprintf(char *out, const char *format, ...) +{ + register int *varg = (int *)(&format); + return print(&out, varg); +}