From 95ccf534a42d895b707e9f270e5c8b711196f1e6 Mon Sep 17 00:00:00 2001 From: juraj Date: Fri, 21 Feb 2020 20:48:19 +0100 Subject: [PATCH] initial commit, compiles for ATTINY84 with TX on PA5 and RX on PA6 --- Makefile | 22 ++++++ README | 28 ++++++++ fifo.c | 27 +++++++ fifo.h | 74 ++++++++++++++++++++ main.c | 22 ++++++ suart.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ suart.h | 18 +++++ 7 files changed, 400 insertions(+) create mode 100644 Makefile create mode 100644 README create mode 100644 fifo.c create mode 100644 fifo.h create mode 100644 main.c create mode 100644 suart.c create mode 100644 suart.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a5b9c03 --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +MCU=attiny84 +CC=avr-gcc +LD=avr-ld +OBJCOPY=avr-objcopy +SIZE=avr-size +AVRDUDE=avrdude +CFLAGS=-Wall -g -Os -mmcu=${MCU} -I. -I.. +TARGET=main + +SRCS=main.c suart.c + +all: + ${CC} ${CFLAGS} -o ${TARGET}.o ${SRCS} + ${LD} -o ${TARGET}.elf ${TARGET}.o + ${OBJCOPY} -j .text -j .data -O ihex ${TARGET}.o ${TARGET}.hex + ${SIZE} -C --mcu=${MCU} ${TARGET}.elf + +flash: + ${AVRDUDE} -p ${MCU} -c usbasp -U flash:w:${TARGET}.hex:i -F -P usb + +clean: + rm -f *.c~ *.o *.elf *.hex \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..cf38ed1 --- /dev/null +++ b/README @@ -0,0 +1,28 @@ +soft-uart von rn-wissen.de, im Original fuer den ATMEGA8, abgeändert für ATTINY84 von juraj + +Einstellungen werde in suart.c getätigt: + +F_CPU ...für richtiges Timing + zB. 1000000 +BAUDRATE ... + zB. 57600 + +--- + +SUART_TXD_PORT ...welches Register zu verwenden ist (SENDEN) + zB. PORTA +SUART_TXD_DDR ... --"-- (SENDEN) + zB. DDRA +SUART_TXD_BIT ... welcher Pin dieses Registers (SENDEN) + zB. PA5 + +--- + +SUART_RXD_PORT ...welches Register zu verwenden ist (EMPFANGEN) + zB. PORTA +SUART_RXD_PIN ... --"-- (EMPFANGEN) + zB. PINA +SUART_RXD_DDR ... --"-- (EMPFANGEN) + zB. DDRA +SUART_RXD_BIT ... welcher Pin dieses Registers (EMPFANGEN) + zB. PA6 diff --git a/fifo.c b/fifo.c new file mode 100644 index 0000000..fb933ed --- /dev/null +++ b/fifo.c @@ -0,0 +1,27 @@ +#include "fifo.h" + +void fifo_init (fifo_t *f, uint8_t *buffer, const uint8_t size) +{ + f->count = 0; + f->pread = f->pwrite = buffer; + f->read2end = f->write2end = f->size = size; +} + +uint8_t fifo_put (fifo_t *f, const uint8_t data) +{ + return _inline_fifo_put (f, data); +} + +uint8_t fifo_get_wait (fifo_t *f) +{ + while (!f->count); + + return _inline_fifo_get (f); +} + +int fifo_get_nowait (fifo_t *f) +{ + if (!f->count) return -1; + + return (int) _inline_fifo_get (f); +} \ No newline at end of file diff --git a/fifo.h b/fifo.h new file mode 100644 index 0000000..aa43cd4 --- /dev/null +++ b/fifo.h @@ -0,0 +1,74 @@ +#ifndef FIFO_H +#define FIFO_H + +#include +#include + +typedef struct +{ + uint8_t volatile count; // # Zeichen im Puffer + uint8_t size; // Puffer-Größe + uint8_t *pread; // Lesezeiger + uint8_t *pwrite; // Schreibzeiger + uint8_t read2end, write2end; // # Zeichen bis zum Überlauf Lese-/Schreibzeiger +} fifo_t; + +extern void fifo_init (fifo_t*, uint8_t* buf, const uint8_t size); +extern uint8_t fifo_put (fifo_t*, const uint8_t data); +extern uint8_t fifo_get_wait (fifo_t*); +extern int fifo_get_nowait (fifo_t*); + +static inline uint8_t +_inline_fifo_put (fifo_t *f, const uint8_t data) +{ + if (f->count >= f->size) + return 0; + + uint8_t * pwrite = f->pwrite; + + *(pwrite++) = data; + + uint8_t write2end = f->write2end; + + if (--write2end == 0) + { + write2end = f->size; + pwrite -= write2end; + } + + f->write2end = write2end; + f->pwrite = pwrite; + + uint8_t sreg = SREG; + cli(); + f->count++; + SREG = sreg; + + return 1; +} + +static inline uint8_t +_inline_fifo_get (fifo_t *f) +{ + uint8_t *pread = f->pread; + uint8_t data = *(pread++); + uint8_t read2end = f->read2end; + + if (--read2end == 0) + { + read2end = f->size; + pread -= read2end; + } + + f->pread = pread; + f->read2end = read2end; + + uint8_t sreg = SREG; + cli(); + f->count--; + SREG = sreg; + + return data; +} + +#endif /* FIFO_H */ \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..55c7b4c --- /dev/null +++ b/main.c @@ -0,0 +1,22 @@ +#define SUART_TXD +#define SUART_RXD + +#include +#include "suart.h" + + +int +main(void) +{ + sei(); + uart_init(); + char c; + +// not there yet, for now only echo +// uart_puts("Hello Parrot!\n"); + + while (1) { + c = uart_getc_wait(); + uart_putc(c); + } +} \ No newline at end of file diff --git a/suart.c b/suart.c new file mode 100644 index 0000000..be0f4a2 --- /dev/null +++ b/suart.c @@ -0,0 +1,209 @@ +#include +#include + +#ifndef SIGNAL +#include +#endif // SIGNAL + +#include "suart.h" + +// Folgende Zeile einkommentieren, falls FIFO verwendet werden soll +#include "fifo.h" + +#define F_CPU 1000000 +#define BAUDRATE 38400 + +#define nop() __asm volatile ("nop") + +#ifdef SUART_TXD + #define SUART_TXD_PORT PORTA + #define SUART_TXD_DDR DDRA + #define SUART_TXD_BIT PA5 + static volatile uint16_t outframe; +#endif // SUART_TXD + +#ifdef SUART_RXD + #define SUART_RXD_PORT PORTA + #define SUART_RXD_PIN PINA + #define SUART_RXD_DDR DDRA + #define SUART_RXD_BIT PA6 + static volatile uint16_t inframe; + static volatile uint8_t inbits, received; + + #ifdef _FIFO_H_ + #define INBUF_SIZE 4 + static uint8_t inbuf[INBUF_SIZE]; + fifo_t infifo; + #else // _FIFO_H_ + static volatile uint8_t indata; + #endif // _FIFO_H_ +#endif // SUART_RXD + +// Initialisierung für einen ATmega8 +// Für andere AVR-Derivate sieht dies vermutlich anders aus: +// Registernamen ändern sich (zB TIMSK0 anstatt TIMSK, etc). +void uart_init() +{ + uint8_t tifr = 0; + uint8_t sreg = SREG; + cli(); + + // Mode #4 für Timer1 + // und volle MCU clock + // IC Noise Cancel + // IC on Falling Edge + TCCR1A = 0; + TCCR1B = (1 << WGM12) | (1 << CS10) | (0 << ICES1) | (1 << ICNC1); + + // OutputCompare für gewünschte Timer1 Frequenz + OCR1A = (uint16_t) ((uint32_t) F_CPU/BAUDRATE); + +#ifdef SUART_RXD + SUART_RXD_DDR &= ~(1 << SUART_RXD_BIT); + SUART_RXD_PORT |= (1 << SUART_RXD_BIT); + TIMSK0 |= (1 << ICIE1); + tifr |= (1 << ICF1) | (1 << OCF1B); +#else + TIMSK0 &= ~(1 << ICIE1); +#endif // SUART_RXD + +#ifdef SUART_TXD + tifr |= (1 << OCF1A); + SUART_TXD_PORT |= (1 << SUART_TXD_BIT); + SUART_TXD_DDR |= (1 << SUART_TXD_BIT); + outframe = 0; +#endif // SUART_TXD + + TIFR1 = tifr; + + SREG = sreg; + +#ifdef _FIFO_H_ + fifo_init (&infifo, inbuf, INBUF_SIZE); +#endif // _FIFO_H_ + +} + +// TRANSMITTER +#ifdef SUART_TXD +void uart_putc (const char c) +{ + do + { + sei(); nop(); cli(); // yield(); + } while (outframe); + + // frame = *.P.7.6.5.4.3.2.1.0.S S=Start(0), P=Stop(1), *=Endemarke(1) + outframe = (3 << 9) | (((uint8_t) c) << 1); + + TIMSK0 |= (1 << OCIE1A); + TIFR1 = (1 << OCF1A); + + sei(); +} +#endif // SUART_TXD +#ifdef SUART_TXD +SIGNAL (SIG_OUTPUT_COMPARE1A) +{ + uint16_t data = outframe; + + if (data & 1) SUART_TXD_PORT |= (1 << SUART_TXD_BIT); + else SUART_TXD_PORT &= ~(1 << SUART_TXD_BIT); + + if (1 == data) + { + TIMSK0 &= ~(1 << OCIE1A); + } + + outframe = data >> 1; +} +#endif // SUART_TXD + +// RECEIVER +#ifdef SUART_RXD +SIGNAL (SIG_INPUT_CAPTURE1) +{ + uint16_t icr1 = ICR1; + uint16_t ocr1a = OCR1A; + + // Eine halbe Bitzeit zu ICR1 addieren (modulo OCR1A) und nach OCR1B + uint16_t ocr1b = icr1 + ocr1a/2; + if (ocr1b >= ocr1a) + ocr1b -= ocr1a; + OCR1B = ocr1b; + + TIFR1 = (1 << OCF1B); + TIMSK0 = (TIMSK0 & ~(1 << ICIE1)) | (1 << OCIE1B); + inframe = 0; + inbits = 0; +} +#endif // SUART_RXD +#ifdef SUART_RXD +SIGNAL (SIG_OUTPUT_COMPARE1B) +{ + uint16_t data = inframe >> 1; + + if (SUART_RXD_PIN & (1 << SUART_RXD_BIT)) + data |= (1 << 9); + + uint8_t bits = inbits+1; + + if (10 == bits) + { + if ((data & 1) == 0) + if (data >= (1 << 9)) + { +#ifdef _FIFO_H_ + _inline_fifo_put (&infifo, data >> 1); +#else + indata = data >> 1; +#endif // _FIFO_H_ + received = 1; + } + + TIMSK0 = (TIMSK0 & ~(1 << OCIE1B)) | (1 << ICIE1); + TIFR1 = (1 << ICF1); + } + else + { + inbits = bits; + inframe = data; + } +} +#endif // SUART_RXD +#ifdef SUART_RXD +#ifdef _FIFO_H_ + +int uart_getc_wait() +{ + return (int) fifo_get_wait (&infifo); +} + +int uart_getc_nowait() +{ + return fifo_get_nowait (&infifo); +} + +#else // _FIFO_H_ + +int uart_getc_wait() +{ + while (!received) {} + received = 0; + + return (int) indata; +} + +int uart_getc_nowait() +{ + if (received) + { + received = 0; + return (int) indata; + } + + return -1; +} + +#endif // _FIFO_H_ +#endif // SUART_RXD \ No newline at end of file diff --git a/suart.h b/suart.h new file mode 100644 index 0000000..f6d573d --- /dev/null +++ b/suart.h @@ -0,0 +1,18 @@ +#ifndef _UART_H_ +#define _UART_H_ + +#define SUART_TXD +#define SUART_RXD + +extern void uart_init(); + +#ifdef SUART_TXD + extern void uart_putc (const char); +#endif // SUART_RXD + +#ifdef SUART_RXD + extern int uart_getc_wait (); + extern int uart_getc_nowait(); +#endif // SUART_RXD + +#endif /* _UART_H_ */ \ No newline at end of file