initial commit, compiles for ATTINY84 with TX on PA5 and RX on PA6
This commit is contained in:
22
Makefile
Normal file
22
Makefile
Normal file
@@ -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
|
||||
28
README
Normal file
28
README
Normal file
@@ -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
|
||||
27
fifo.c
Normal file
27
fifo.c
Normal file
@@ -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);
|
||||
}
|
||||
74
fifo.h
Normal file
74
fifo.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef FIFO_H
|
||||
#define FIFO_H
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
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 */
|
||||
22
main.c
Normal file
22
main.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#define SUART_TXD
|
||||
#define SUART_RXD
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#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);
|
||||
}
|
||||
}
|
||||
209
suart.c
Normal file
209
suart.c
Normal file
@@ -0,0 +1,209 @@
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#ifndef SIGNAL
|
||||
#include <avr/signal.h>
|
||||
#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
|
||||
18
suart.h
Normal file
18
suart.h
Normal file
@@ -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_ */
|
||||
Reference in New Issue
Block a user