Last active
August 29, 2015 14:25
-
-
Save osvein/fb4d7b863e76e40c6161 to your computer and use it in GitHub Desktop.
USART with stdio and flow control for the AVR
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Spor - real-time tracking using GPS and SMS | |
| * Copyright (C) 2015 Oskar Sveinsen | |
| * | |
| * This program is free software: you can redistribute it and/or modify | |
| * it under the terms of the GNU Affero General Public License as published by | |
| * the Free Software Foundation, either version 3 of the License, or | |
| * (at your option) any later version. | |
| * | |
| * This program is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Affero General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Affero General Public License | |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| */ | |
| #include <stdbool.h> | |
| #include <avr/sfr_defs.h> | |
| #include "usart.h" | |
| static inline char *put_head_(struct usart_buf *); | |
| static inline char *get_tail_(struct usart_buf *); | |
| FILE usart_stream = FDEV_SETUP_STREAM(usart_putc, usart_getc, _FDEV_SETUP_RW); | |
| FILE *usart_open(struct usart_mmap mmap, unsigned int ubrr, bool u2x, struct usart_flowctl flowctl, struct usart_buf buf_rx, struct usart_buf buf_tx) { | |
| usart_mmap = mmap; | |
| *(usart_mmap.ubrrl) = (char)ubrr; | |
| *(usart_mmap.ubrrh) = (char)(ubrr >> 8); | |
| if (u2x) { | |
| *(usart_mmap.ucsra) |= _BV(U2X); | |
| } | |
| else { | |
| *(usart_mmap.ucsra) &= ~_BV(U2X); | |
| } | |
| usart_flowctl = flowctl; | |
| usart_buf_rx = buf_rx; | |
| usart_buf_tx = buf_tx; | |
| return &usart_stream; | |
| } | |
| FILE *usart_open(struct usart_mmap mmap, unsigned int ubrr, bool u2x, struct usart_flowctl flowctl) { | |
| return usart_open(mmap, ubrr, u2x, flowctl, usart_buf_null, usart_buf_null); | |
| } | |
| FILE *usart_open(struct usart_mmap mmap, unsigned int ubrr, bool u2x) { | |
| return usart_open(mmap, ubrr, u2x, usart_flowctl_null, usart_buf_null); | |
| } | |
| FILE *usart_open(struct usart_mmap mmap) { | |
| unsigned int ubrr = *(mmap.ubrrl) | (*(mmap.ubrrh) << 8); | |
| bool u2x = (*(mmap.ucsra) & _BV(U2X)) ? true : false; | |
| return usart_open(mmap, ubrr, u2x); | |
| } | |
| int usart_getc(FILE *stream) { | |
| if (usart_buf_rx.limit_tail != NULL) { | |
| return *((usart_buf_rx.tail)++); | |
| } | |
| else { | |
| loop_until_bit_is_set(*(usart_mmap.ucsra), 7); | |
| return *(usart_mmap.udr); | |
| } | |
| } | |
| int usart_putc(char c, FILE *stream) { | |
| if (usart_buf_tx.limit_tail != NULL) { | |
| *(++(usart_buf_tx.head)) = c; | |
| } | |
| else { | |
| loop_until_bit_is_set(*(usart_mmap.ucsra), 5); | |
| *(usart_mmap.udr) = c; | |
| } | |
| return c; | |
| } | |
| ISR(USART_RX_vect) { | |
| if (usart_buf_rx.limit_tail != NULL) { | |
| *(++(usart_buf_rx.head)) = *(usart_mmap.udr); | |
| } | |
| } | |
| ISR(USART_UDRE_vect) { | |
| if (usart_buf_tx.limit_tail != NULL) { | |
| if (usart_buf_rx.tail > usart_buf_rx.limit_head) { | |
| usart_buf_rx.tail = usart | |
| } | |
| *(usart_mmap.udr) = *((usart_buf_rx.tail)++); | |
| } | |
| } | |
| char *put_head_(struct usart_buf *buf) { | |
| buf->head++; | |
| if (buf->head > buf->limit_head || buf->head < buf->limit_tail) { | |
| buf->head = buf->limit_tail; | |
| } | |
| return *(buf->head); | |
| } | |
| char *get_tail_(struct usart_buf *buf) { | |
| char c = *(buf->tail++); | |
| if (buf->tail > buf->limit_head || buf->tail < buf->limit_tail) { | |
| buf->tail = buf->limit_tail; | |
| } | |
| return c; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Spor - real-time tracking using GPS and SMS | |
| * Copyright (C) 2015 Oskar Sveinsen | |
| * | |
| * This program is free software: you can redistribute it and/or modify | |
| * it under the terms of the GNU Affero General Public License as published by | |
| * the Free Software Foundation, either version 3 of the License, or | |
| * (at your option) any later version. | |
| * | |
| * This program is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Affero General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Affero General Public License | |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| */ | |
| #ifndef USART_H | |
| #define USART_H | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif | |
| struct usart_mmap { | |
| char *udr; // USART I/O Data Register n | |
| char *ucsra; // USART Control and Status Register n A | |
| char *ucsrb; // USART Control and Status Register n B | |
| char *ucsrc; // USART Control and Status Register n C | |
| char *ubrrh; // USART Baud Rate Registers - high byte | |
| char *ubrrl; // USART Baud Rate Registers - low byte | |
| }; | |
| struct usart_flowctl { | |
| char mode; // flow control mode | |
| #define USART_FLOWCTL_MODE_NULL 0x0 | |
| #define USART_FLOWCTL_MODE_SOFT 0x5 | |
| #define USART_FLOWCTL_MODE_HARD (USART_FLOWCTL_MODE_SOFT << 1) | |
| #define USART_FLOWCTL_MODE_ALL (USART_FLOWCTL_MODE_SOFT | USART_FLOWCTL_MODE_HARD) | |
| #define USART_FLOWCTL_MODE_TX 0x3 | |
| #define USART_FLOWCTL_MODE_RX (USART_FLOWCTL_MODE_TX << 2) | |
| char soft_resume; // software flow control character to resume flow | |
| char soft_stop; // software flow control character to stop flow | |
| bool (*hard_get)(void); // get hardware transmit flow control | |
| void (*hard_set)(bool); // set hardware receive flow control | |
| }; | |
| extern struct usart_flowctl usart_flowctl_null = { | |
| .mode = USART_FLOWCTL_MODE_NULL, | |
| }; | |
| struct usart_buf { | |
| char *limit_tail; | |
| char *limit_head; | |
| char *tail; | |
| char *head; | |
| }; | |
| extern struct usart_buf usart_buf_null = { | |
| .limit_tail = NULL, | |
| }; | |
| FILE *usart_open(struct usart_mmap, unsigned int ubrr, bool u2x, struct usart_flowctl, struct usart_buf buf_rx, struct usart_buf buf_tx); | |
| FILE *usart_open(struct usart_mmap, unsigned int ubrr, bool u2x, struct usart_flowctl); | |
| FILE *usart_open(struct usart_mmap, unsigned int ubrr, bool u2x); | |
| FILE *usart_open(struct usart_mmap); | |
| void usart_putc(char, FILE *); | |
| void usart_getc(FILE *); | |
| extern const FILE usart_stream; | |
| extern struct usart_mmap usart_mmap; | |
| extern struct usart_flowctl usart_flowctl; | |
| extern struct usart_buf usart_buf_rx; | |
| extern struct usart_buf usart_buf_tx; | |
| #ifdef __cplusplus | |
| } // extern "C" | |
| #endif | |
| #endif // USART_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment