uart.h


// uart.h
//
//  Beware!  UART output and input "polarity" may not be what you want!!!
//

#ifndef __UART_H
#define __UART_H

#include "iodefs.h"
#include "progmem.h"

//
// Note: Only use #define TX_FALL_DELAY for baud rates faster than 38400
//
#ifndef TX_FALL_DELAY
#define TX_FALL_DELAY 0
#define TX_FALL_DELAY_CODE 
#else
#undef TX_FALL_DELAY
#define TX_FALL_DELAY 3
#define TX_FALL_DELAY_CODE     \
                "nop" "\n\t"   \
                "nop" "\n\t"   \
                "nop" "\n\t"
#endif
//
//  Number of 3-clock loops in one bit (i.e., one baud time)
//
#define UART_TX_COUNT \
        ((2*((CLOCK + (BAUD_RATE/2))/BAUD_RATE - 9 - TX_FALL_DELAY) + 3) / 6)

#define UART_RX_COUNT \
        ((2*((CLOCK + (BAUD_RATE/2))/BAUD_RATE-8) + 3) / 6)

#ifndef STOP_BITS
#define STOP_BITS 1
#endif

#ifndef BAUD_RATE
#define BAUD_RATE 9600
#endif

#define __uart_reset(port, bit)               \
        asm volatile (                        \
                "cbi %0, %1" "\n\t"           \
                "sbi %0-1, %1"                \
                : /* no outputs */            \
                : "I" ((uint8_t)(port)),      \
                  "I" ((uint8_t)(bit))        \
        )

#define __uart_tx(port, bit, count)           \
        asm volatile (                        \
                "mov __tmp_reg__,%2" "\n"     \
        ".L_%=:\t"                            \
                "dec __tmp_reg__" "\n\t"      \
                "brne .L_%=" "\n\t"           \
                "cbi %0, %1" "\n\t"           \
                "sbi %0-1, %1" "\n\t"         \
                : /* no outputs */            \
                : "I" ((uint8_t)(port)),      \
                  "I" ((uint8_t)(bit)),       \
                  "r" ((uint8_t)(count))      \
        )

#define __uart_rx(port, bit)                  \
        asm volatile (                        \
                "cbi %0-1, %1" "\n\t"         \
                "sbi %0, %1" "\n\t"           \
                : /* no outputs */            \
                : "I" ((uint8_t)(port)),      \
                  "I" ((uint8_t)(bit))        \
        )

#define __putchar(port, bit, ch, stops, count)\
        asm volatile (                        \
                "ldi r23, 9+%3" "\n\t"        \
                "mov r24, %2" "\n\t"          \
                "com r24" "\n\t"              \
                "sec" "\n"                    \
        ".L0_%=:\t"                           \
                "brcc .L1_%=" "\n\t"          \
                TX_FALL_DELAY_CODE            \
                "sbi %0, %1" "\n\t"           \
                "rjmp .L2_%=" "\n"            \
        ".L1_%=:\t"                           \
                "cbi %0, %1" "\n\t"           \
                TX_FALL_DELAY_CODE            \
                "nop" "\n"                    \
        ".L2_%=:\t"                           \
                "mov __tmp_reg__,%4" "\n"     \
        ".L3_%=:\t"                           \
                "dec __tmp_reg__" "\n\t"      \
                "brne .L3_%=" "\n\t"          \
                "lsr r24" "\n\t"              \
                "dec r23" "\n\t"              \
                "brne .L0_%="                 \
                : /* no outputs */            \
                : "I" ((uint8_t)(port)),      \
                  "I" ((uint8_t)(bit)),       \
                  "r" ((uint8_t)(ch)),        \
                  "I" ((uint8_t)(stops)),     \
                  "r" ((uint8_t)(count))      \
                : "r23", "r24"                \
        )

#define __getchar(port, bit, stops, count) ({ \
        unsigned char ch;                     \
        asm volatile (                        \
                "ldi r23,8+1" "\n"            \
        ".L1_%=:\t"                           \
                "sbis %1-2,%2" "\n\t"         \
                "rjmp .L1_%=" "\n\t"          \
                "mov __tmp_reg__,%4" "\n\t"   \
                "lsr __tmp_reg__" "\n"        \
        ".L0_%=:\t"                           \
                "dec __tmp_reg__" "\n\t"      \
                "brne .L0_%=" "\n"            \
        ".L2_%=:\t"                           \
                "mov __tmp_reg__,%4" "\n"     \
        ".L3_%=:\t"                           \
                "dec __tmp_reg__" "\n\t"      \
                "brne .L3_%=" "\n\t"          \
                "clc" "\n\t"                  \
                "sbis %1-2,%2" "\n\t"         \
                "sec" "\n\t"                  \
                "dec r23" "\n\t"              \
                "breq .L4_%=" "\n\t"          \
                "ror %0" "\n\t"               \
                "rjmp .L2_%=" "\n"            \
        ".L4_%=:\t"                           \
                : "=&r" (ch)                  \
                : "I" ((uint8_t)(port)),      \
                  "I" ((uint8_t)(bit)),       \
                  "I" ((uint8_t)(stops)),     \
                  "r" ((uint8_t)(count))      \
                : "r23"                       \
        );                                    \
        ch;                                   \
})

#define _uart_reset() __uart_reset(TX_PORT, TX_BIT)
#define _uart_tx() __uart_tx(TX_PORT, TX_BIT, 2*(UART_TX_COUNT))
#define _uart_rx() __uart_rx(TX_PORT, TX_BIT)
#define _putchar(ch) __putchar(TX_PORT, TX_BIT, ch, STOP_BITS, UART_TX_COUNT)
#define _getchar() __getchar(TX_PORT, TX_BIT, STOP_BITS, UART_RX_COUNT);

void uart_tx(void);
void uart_rx(void);

#include "puthexb.h"
#include "getchar.h"
#include "putchar.h"
#include "crlf.h"
#include "pmputstr.h"

#endif /* __UART_H */

Back