Mercurial > ~darius > hgwebdir.cgi > avr-lib
diff cons.c @ 0:3879f487b661
Initial commit of routines I copy and paste.
Need work to make them more portable (esp cons)
author | darius@Inchoate |
---|---|
date | Wed, 11 Mar 2009 16:42:27 +1030 |
parents | |
children | 15d89caaf516 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cons.c Wed Mar 11 16:42:27 2009 +1030 @@ -0,0 +1,179 @@ +/* + * Console code for AVR board + * + * Copyright (c) 2008 + * Daniel O'Connor <darius@dons.net.au>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <avr/interrupt.h> +#include <avr/pgmspace.h> +#include "cons.h" + +#define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1) + +/* Receive buffer storage */ +consbuf_t cmd; + +/* + * Stub to use with fdevopen + * + * We ignore f and always succeed + */ +static int _putc(char c, FILE *f) { + cons_putc(c); + return(0); +} + +/* + * Stub to use with fdevopen + * + * We ignore f and always succeed + */ +static int _getc(FILE *f) { + return(cons_getc()); +} + +void +cons_init(void) { + UBRR0 = UART_BAUD_SELECT(38400, F_CPU); + + /* Enable receiver and transmitter. Turn on rx interrupts */ + UCSR0A = 0; + UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0); + UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); + + fdevopen(_putc, NULL); /* Open stdout */ + fdevopen(NULL, _getc); /* Open stdin */ +} + +int +cons_putc(char c) { + loop_until_bit_is_set(UCSR0A, UDRE0); + UDR0 = c; + + return(0); +} + +void +cons_putsP(const char *addr) { + char c; + + while ((c = pgm_read_byte_near(addr++))) + cons_putc(c); +} + +void +cons_puts(const char *addr) { + while (*addr) + cons_putc(*addr++); +} + +void +cons_puts_dec(uint8_t a, uint8_t l) { + char s[4]; + + if (l && a < 10) + cons_putsP(PSTR("0")); + cons_puts(utoa(a, s, 10)); +} + +void +cons_puts_hex(uint8_t a) { + char s[3]; + + if (a < 0x10) + cons_putc('0'); + + cons_puts(utoa(a, s, 16)); +} + +char +cons_getc(void) { + while (!(UCSR0A & _BV(RXC0))) + ; + + return (UDR0); +} + +/* Rx complete */ +ISR(USART0_RX_vect) { + volatile char pit; + char c; + + while (UCSR0A & _BV(RXC0)) { + /* 255 means we're waiting for main to process the command, + just throw stuff away + */ + if (cmd.state == 255) { + pit = UDR0; + continue; + } + c = UDR0; + + /* End of line? */ + if (c == '\n' || c == '\r') { + cmd.buf[cmd.state] = '\0'; + printf_P(PSTR("\r\n")); + cmd.len = cmd.state; + cmd.state = 255; + continue; + } + + /* Backspace/delete */ + if (c == 0x08 || c == 0x7f) { + if (cmd.state > 0) { + cmd.state--; + printf_P(PSTR("\010\040\010")); + } + continue; + } + + /* Anything unprintable just ignore it */ + if (!isprint(c)) + continue; + + cmd.buf[cmd.state] = tolower(c); + + /* Echo back to the user */ + cons_putc(cmd.buf[cmd.state]); + + cmd.state++; + /* Over flow? */ + if (cmd.state == ((sizeof(cmd.buf) / sizeof(cmd.buf[0])) - 1)) { + printf_P(PSTR("\r\nLine too long")); + cmd.state = 0; + continue; + } + } +} + +/* Tx complete */ +ISR(USART0_TX_vect) { + +} +