arduino-0018-windows
This commit is contained in:
parent
157fd6f1a1
commit
f39fc49523
5182 changed files with 950586 additions and 0 deletions
|
@ -0,0 +1,82 @@
|
|||
PRG = stdiodemo
|
||||
OBJ = stdiodemo.o hd44780.o lcd.o uart.o
|
||||
MCU_TARGET = atmega16
|
||||
OPTIMIZE = -Os
|
||||
|
||||
DEFS =
|
||||
LIBS =
|
||||
|
||||
# You should not have to change anything below here.
|
||||
|
||||
CC = avr-gcc
|
||||
|
||||
CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
|
||||
LDFLAGS = -Wl,-Map,$(PRG).map
|
||||
|
||||
OBJCOPY = avr-objcopy
|
||||
OBJDUMP = avr-objdump
|
||||
|
||||
all: $(PRG).elf lst text eeprom
|
||||
|
||||
$(PRG).elf: $(OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak
|
||||
rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)
|
||||
|
||||
lst: $(PRG).lst
|
||||
|
||||
%.lst: %.elf
|
||||
$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
# Rules for building the .text rom images
|
||||
|
||||
text: hex bin srec
|
||||
|
||||
hex: $(PRG).hex
|
||||
bin: $(PRG).bin
|
||||
srec: $(PRG).srec
|
||||
|
||||
%.hex: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O ihex $< $@
|
||||
|
||||
%.srec: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O srec $< $@
|
||||
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O binary $< $@
|
||||
|
||||
# Rules for building the .eeprom rom images
|
||||
|
||||
eeprom: ehex ebin esrec
|
||||
|
||||
ehex: $(PRG)_eeprom.hex
|
||||
ebin: $(PRG)_eeprom.bin
|
||||
esrec: $(PRG)_eeprom.srec
|
||||
|
||||
%_eeprom.hex: %.elf
|
||||
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||
|
||||
%_eeprom.srec: %.elf
|
||||
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@
|
||||
|
||||
%_eeprom.bin: %.elf
|
||||
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@
|
||||
|
||||
# Every thing below here is used by avr-libc's build system and can be ignored
|
||||
# by the casual user.
|
||||
|
||||
JPEGFILES = stdiodemo-setup.jpg
|
||||
|
||||
JPEG2PNM = jpegtopnm
|
||||
PNM2EPS = pnmtops
|
||||
JPEGRESOLUTION = 180
|
||||
EXTRA_CLEAN_FILES = *.hex *.bin *.srec *.eps
|
||||
|
||||
dox: ${JPEGFILES:.jpg=.eps}
|
||||
|
||||
%.eps: %.jpg
|
||||
$(JPEG2PNM) $< |\
|
||||
$(PNM2EPS) -noturn -dpi $(JPEGRESOLUTION) -equalpixels \
|
||||
> $@
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <joerg@FreeBSD.ORG> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* General stdiodemo defines
|
||||
*
|
||||
* $Id: defines.h,v 1.2 2006/10/08 21:47:36 joerg_wunsch Exp $
|
||||
*/
|
||||
|
||||
/* CPU frequency */
|
||||
#define F_CPU 1000000UL
|
||||
|
||||
/* UART baud rate */
|
||||
#define UART_BAUD 9600
|
||||
|
||||
/* HD44780 LCD port connections */
|
||||
#define HD44780_PORT A
|
||||
#define HD44780_RS PORT6
|
||||
#define HD44780_RW PORT4
|
||||
#define HD44780_E PORT5
|
||||
/* The data bits have to be in ascending order. */
|
||||
#define HD44780_D4 PORT0
|
||||
#define HD44780_D5 PORT1
|
||||
#define HD44780_D6 PORT2
|
||||
#define HD44780_D7 PORT3
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <joerg@FreeBSD.ORG> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* HD44780 LCD display driver
|
||||
*
|
||||
* The LCD controller is used in 4-bit mode with a full bi-directional
|
||||
* interface (i.e. R/~W is connected) so the busy flag can be read.
|
||||
*
|
||||
* $Id: hd44780.c,v 1.3 2006/10/08 21:47:36 joerg_wunsch Exp $
|
||||
*/
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#include "hd44780.h"
|
||||
|
||||
#define GLUE(a, b) a##b
|
||||
#define PORT(x) GLUE(PORT, x)
|
||||
#define PIN(x) GLUE(PIN, x)
|
||||
#define DDR(x) GLUE(DDR, x)
|
||||
|
||||
#define HD44780_PORTOUT PORT(HD44780_PORT)
|
||||
#define HD44780_PORTIN PIN(HD44780_PORT)
|
||||
#define HD44780_DDR DDR(HD44780_PORT)
|
||||
|
||||
#define HD44780_DATABITS \
|
||||
(_BV(HD44780_D4)|_BV(HD44780_D5)|_BV(HD44780_D6)|_BV(HD44780_D7))
|
||||
|
||||
#define HD44780_BUSYFLAG 0x80
|
||||
|
||||
/*
|
||||
* Send one pulse to the E signal (enable). Mind the timing
|
||||
* constraints. If readback is set to true, read the HD44780 data
|
||||
* pins right before the falling edge of E, and return that value.
|
||||
*/
|
||||
static inline uint8_t
|
||||
hd44780_pulse_e(bool readback) __attribute__((always_inline));
|
||||
|
||||
static inline uint8_t
|
||||
hd44780_pulse_e(bool readback)
|
||||
{
|
||||
uint8_t x;
|
||||
|
||||
HD44780_PORTOUT |= _BV(HD44780_E);
|
||||
/*
|
||||
* Guarantee at least 500 ns of pulse width. For high CPU
|
||||
* frequencies, a delay loop is used. For lower frequencies, NOPs
|
||||
* are used, and at or below 1 MHz, the native pulse width will
|
||||
* already be 1 us or more so no additional delays are needed.
|
||||
*/
|
||||
#if F_CPU > 4000000UL
|
||||
_delay_us(0.5);
|
||||
#else
|
||||
/*
|
||||
* When reading back, we need one additional NOP, as the value read
|
||||
* back from the input pin is sampled close to the beginning of a
|
||||
* CPU clock cycle, while the previous edge on the output pin is
|
||||
* generated towards the end of a CPU clock cycle.
|
||||
*/
|
||||
if (readback)
|
||||
__asm__ volatile("nop");
|
||||
# if F_CPU > 1000000UL
|
||||
__asm__ volatile("nop");
|
||||
# if F_CPU > 2000000UL
|
||||
__asm__ volatile("nop");
|
||||
__asm__ volatile("nop");
|
||||
# endif /* F_CPU > 2000000UL */
|
||||
# endif /* F_CPU > 1000000UL */
|
||||
#endif
|
||||
if (readback)
|
||||
x = HD44780_PORTIN & HD44780_DATABITS;
|
||||
else
|
||||
x = 0;
|
||||
HD44780_PORTOUT &= ~_BV(HD44780_E);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send one nibble out to the LCD controller.
|
||||
*/
|
||||
static void
|
||||
hd44780_outnibble(uint8_t n, uint8_t rs)
|
||||
{
|
||||
uint8_t x;
|
||||
|
||||
HD44780_PORTOUT &= ~_BV(HD44780_RW);
|
||||
if (rs)
|
||||
HD44780_PORTOUT |= _BV(HD44780_RS);
|
||||
else
|
||||
HD44780_PORTOUT &= ~_BV(HD44780_RS);
|
||||
x = (HD44780_PORTOUT & ~HD44780_DATABITS) | ((n << HD44780_D4) & HD44780_DATABITS);
|
||||
HD44780_PORTOUT = x;
|
||||
(void)hd44780_pulse_e(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send one byte to the LCD controller. As we are in 4-bit mode, we
|
||||
* have to send two nibbles.
|
||||
*/
|
||||
void
|
||||
hd44780_outbyte(uint8_t b, uint8_t rs)
|
||||
{
|
||||
hd44780_outnibble(b >> 4, rs);
|
||||
hd44780_outnibble(b & 0xf, rs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read one nibble from the LCD controller.
|
||||
*/
|
||||
static uint8_t
|
||||
hd44780_innibble(uint8_t rs)
|
||||
{
|
||||
uint8_t x;
|
||||
|
||||
HD44780_PORTOUT |= _BV(HD44780_RW);
|
||||
HD44780_DDR &= ~HD44780_DATABITS;
|
||||
if (rs)
|
||||
HD44780_PORTOUT |= _BV(HD44780_RS);
|
||||
else
|
||||
HD44780_PORTOUT &= ~_BV(HD44780_RS);
|
||||
x = hd44780_pulse_e(true);
|
||||
HD44780_DDR |= HD44780_DATABITS;
|
||||
HD44780_PORTOUT &= ~_BV(HD44780_RW);
|
||||
|
||||
return (x & HD44780_DATABITS) >> HD44780_D4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read one byte (i.e. two nibbles) from the LCD controller.
|
||||
*/
|
||||
uint8_t
|
||||
hd44780_inbyte(uint8_t rs)
|
||||
{
|
||||
uint8_t x;
|
||||
|
||||
x = hd44780_innibble(rs) << 4;
|
||||
x |= hd44780_innibble(rs);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait until the busy flag is cleared.
|
||||
*/
|
||||
void
|
||||
hd44780_wait_ready(void)
|
||||
{
|
||||
while (hd44780_incmd() & HD44780_BUSYFLAG) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the LCD controller.
|
||||
*
|
||||
* The initialization sequence has a mandatory timing so the
|
||||
* controller can safely recognize the type of interface desired.
|
||||
* This is the only area where timed waits are really needed as
|
||||
* the busy flag cannot be probed initially.
|
||||
*/
|
||||
void
|
||||
hd44780_init(void)
|
||||
{
|
||||
|
||||
HD44780_DDR = _BV(HD44780_RS) | _BV(HD44780_RW) | _BV(HD44780_E)
|
||||
| HD44780_DATABITS;
|
||||
|
||||
_delay_ms(15); /* 40 ms needed for Vcc = 2.7 V */
|
||||
hd44780_outnibble(HD44780_FNSET(1, 0, 0) >> 4, 0);
|
||||
_delay_ms(4.1);
|
||||
hd44780_outnibble(HD44780_FNSET(1, 0, 0) >> 4, 0);
|
||||
_delay_ms(0.1);
|
||||
hd44780_outnibble(HD44780_FNSET(1, 0, 0) >> 4, 0);
|
||||
|
||||
hd44780_outnibble(HD44780_FNSET(0, 1, 0) >> 4, 0);
|
||||
hd44780_wait_ready();
|
||||
hd44780_outcmd(HD44780_FNSET(0, 1, 0));
|
||||
hd44780_wait_ready();
|
||||
hd44780_outcmd(HD44780_DISPCTL(0, 0, 0));
|
||||
hd44780_wait_ready();
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <joerg@FreeBSD.ORG> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* HD44780 LCD display driver
|
||||
*
|
||||
* $Id: hd44780.h,v 1.1 2005/12/28 21:38:59 joerg_wunsch Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Send byte b to the LCD. rs is the RS signal (register select), 0
|
||||
* selects instruction register, 1 selects the data register.
|
||||
*/
|
||||
void hd44780_outbyte(uint8_t b, uint8_t rs);
|
||||
|
||||
/*
|
||||
* Read one byte from the LCD controller. rs is the RS signal, 0
|
||||
* selects busy flag (bit 7) and address counter, 1 selects the data
|
||||
* register.
|
||||
*/
|
||||
uint8_t hd44780_inbyte(uint8_t rs);
|
||||
|
||||
/*
|
||||
* Wait for the busy flag to clear.
|
||||
*/
|
||||
void hd44780_wait_ready(void);
|
||||
|
||||
/*
|
||||
* Initialize the LCD controller hardware.
|
||||
*/
|
||||
void hd44780_init(void);
|
||||
|
||||
|
||||
/* Send a command to the LCD controller. */
|
||||
#define hd44780_outcmd(n) hd44780_outbyte((n), 0)
|
||||
|
||||
/* Send a data byte to the LCD controller. */
|
||||
#define hd44780_outdata(n) hd44780_outbyte((n), 1)
|
||||
|
||||
/* Read the address counter and busy flag from the LCD. */
|
||||
#define hd44780_incmd() hd44780_inbyte(0)
|
||||
|
||||
/* Read the current data byte from the LCD. */
|
||||
#define hd44780_indata() hd44780_inbyte(1)
|
||||
|
||||
|
||||
/* Clear LCD display command. */
|
||||
#define HD44780_CLR \
|
||||
0x01
|
||||
|
||||
/* Home cursor command. */
|
||||
#define HD44780_HOME \
|
||||
0x02
|
||||
|
||||
/*
|
||||
* Select the entry mode. inc determines whether the address counter
|
||||
* auto-increments, shift selects an automatic display shift.
|
||||
*/
|
||||
#define HD44780_ENTMODE(inc, shift) \
|
||||
(0x04 | ((inc)? 0x02: 0) | ((shift)? 1: 0))
|
||||
|
||||
/*
|
||||
* Selects disp[lay] on/off, cursor on/off, cursor blink[ing]
|
||||
* on/off.
|
||||
*/
|
||||
#define HD44780_DISPCTL(disp, cursor, blink) \
|
||||
(0x08 | ((disp)? 0x04: 0) | ((cursor)? 0x02: 0) | ((blink)? 1: 0))
|
||||
|
||||
/*
|
||||
* With shift = 1, shift display right or left.
|
||||
* With shift = 0, move cursor right or left.
|
||||
*/
|
||||
#define HD44780_SHIFT(shift, right) \
|
||||
(0x10 | ((shift)? 0x08: 0) | ((right)? 0x04: 0))
|
||||
|
||||
/*
|
||||
* Function set. if8bit selects an 8-bit data path, twoline arranges
|
||||
* for a two-line display, font5x10 selects the 5x10 dot font (5x8
|
||||
* dots if clear).
|
||||
*/
|
||||
#define HD44780_FNSET(if8bit, twoline, font5x10) \
|
||||
(0x20 | ((if8bit)? 0x10: 0) | ((twoline)? 0x08: 0) | \
|
||||
((font5x10)? 0x04: 0))
|
||||
|
||||
/*
|
||||
* Set the next character generator address to addr.
|
||||
*/
|
||||
#define HD44780_CGADDR(addr) \
|
||||
(0x40 | ((addr) & 0x3f))
|
||||
|
||||
/*
|
||||
* Set the next display address to addr.
|
||||
*/
|
||||
#define HD44780_DDADDR(addr) \
|
||||
(0x80 | ((addr) & 0x7f))
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <joerg@FreeBSD.ORG> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Stdio demo, upper layer of LCD driver.
|
||||
*
|
||||
* $Id: lcd.c,v 1.1 2005/12/28 21:38:59 joerg_wunsch Exp $
|
||||
*/
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#include <util/delay.h>
|
||||
|
||||
#include "hd44780.h"
|
||||
#include "lcd.h"
|
||||
|
||||
/*
|
||||
* Setup the LCD controller. First, call the hardware initialization
|
||||
* function, then adjust the display attributes we want.
|
||||
*/
|
||||
void
|
||||
lcd_init(void)
|
||||
{
|
||||
|
||||
hd44780_init();
|
||||
|
||||
/*
|
||||
* Clear the display.
|
||||
*/
|
||||
hd44780_outcmd(HD44780_CLR);
|
||||
hd44780_wait_ready();
|
||||
|
||||
/*
|
||||
* Entry mode: auto-increment address counter, no display shift in
|
||||
* effect.
|
||||
*/
|
||||
hd44780_outcmd(HD44780_ENTMODE(1, 0));
|
||||
hd44780_wait_ready();
|
||||
|
||||
/*
|
||||
* Enable display, activate non-blinking cursor.
|
||||
*/
|
||||
hd44780_outcmd(HD44780_DISPCTL(1, 1, 0));
|
||||
hd44780_wait_ready();
|
||||
}
|
||||
|
||||
/*
|
||||
* Send character c to the LCD display. After a '\n' has been seen,
|
||||
* the next character will first clear the display.
|
||||
*/
|
||||
int
|
||||
lcd_putchar(char c, FILE *unused)
|
||||
{
|
||||
static bool nl_seen;
|
||||
|
||||
if (nl_seen && c != '\n')
|
||||
{
|
||||
/*
|
||||
* First character after newline, clear display and home cursor.
|
||||
*/
|
||||
hd44780_wait_ready();
|
||||
hd44780_outcmd(HD44780_CLR);
|
||||
hd44780_wait_ready();
|
||||
hd44780_outcmd(HD44780_HOME);
|
||||
hd44780_wait_ready();
|
||||
hd44780_outcmd(HD44780_DDADDR(0));
|
||||
|
||||
nl_seen = false;
|
||||
}
|
||||
if (c == '\n')
|
||||
{
|
||||
nl_seen = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
hd44780_wait_ready();
|
||||
hd44780_outdata(c);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <joerg@FreeBSD.ORG> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Stdio demo, upper layer of LCD driver.
|
||||
*
|
||||
* $Id: lcd.h,v 1.1 2005/12/28 21:38:59 joerg_wunsch Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initialize LCD controller. Performs a software reset.
|
||||
*/
|
||||
void lcd_init(void);
|
||||
|
||||
/*
|
||||
* Send one character to the LCD.
|
||||
*/
|
||||
int lcd_putchar(char c, FILE *stream);
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <joerg@FreeBSD.ORG> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Stdio demo
|
||||
*
|
||||
* $Id: stdiodemo.c,v 1.1 2005/12/28 21:38:59 joerg_wunsch Exp $
|
||||
*/
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include <util/delay.h>
|
||||
|
||||
#include "lcd.h"
|
||||
#include "uart.h"
|
||||
|
||||
/*
|
||||
* Do all the startup-time peripheral initializations.
|
||||
*/
|
||||
static void
|
||||
ioinit(void)
|
||||
{
|
||||
uart_init();
|
||||
lcd_init();
|
||||
}
|
||||
|
||||
FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
|
||||
FILE lcd_str = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE);
|
||||
|
||||
static void
|
||||
delay_1s(void)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
_delay_ms(10);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
uint8_t i;
|
||||
char buf[20], s[20];
|
||||
|
||||
ioinit();
|
||||
|
||||
stdout = stdin = &uart_str;
|
||||
stderr = &lcd_str;
|
||||
|
||||
fprintf(stderr, "Hello world!\n");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
printf_P(PSTR("Enter command: "));
|
||||
if (fgets(buf, sizeof buf - 1, stdin) == NULL)
|
||||
break;
|
||||
if (tolower(buf[0]) == 'q')
|
||||
break;
|
||||
|
||||
switch (tolower(buf[0]))
|
||||
{
|
||||
default:
|
||||
printf("Unknown command: %s\n", buf);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
if (sscanf(buf, "%*s %s", s) > 0)
|
||||
{
|
||||
fprintf(&lcd_str, "Got %s\n", s);
|
||||
printf("OK\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("sscanf() failed\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
if (sscanf(buf, "%*s %s", s) > 0)
|
||||
{
|
||||
fprintf(&uart_str, "Got %s\n", s);
|
||||
printf("OK\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("sscanf() failed\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Bye-bye");
|
||||
delay_1s();
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
putc('.', stderr);
|
||||
delay_1s();
|
||||
}
|
||||
fprintf(stderr, "\n ");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <joerg@FreeBSD.ORG> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Stdio demo, UART implementation
|
||||
*
|
||||
* $Id: uart.c,v 1.1 2005/12/28 21:38:59 joerg_wunsch Exp $
|
||||
*/
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
/*
|
||||
* Initialize the UART to 9600 Bd, tx/rx, 8N1.
|
||||
*/
|
||||
void
|
||||
uart_init(void)
|
||||
{
|
||||
#if F_CPU < 2000000UL && defined(U2X)
|
||||
UCSRA = _BV(U2X); /* improve baud rate error by using 2x clk */
|
||||
UBRRL = (F_CPU / (8UL * UART_BAUD)) - 1;
|
||||
#else
|
||||
UBRRL = (F_CPU / (16UL * UART_BAUD)) - 1;
|
||||
#endif
|
||||
UCSRB = _BV(TXEN) | _BV(RXEN); /* tx/rx enable */
|
||||
}
|
||||
|
||||
/*
|
||||
* Send character c down the UART Tx, wait until tx holding register
|
||||
* is empty.
|
||||
*/
|
||||
int
|
||||
uart_putchar(char c, FILE *stream)
|
||||
{
|
||||
|
||||
if (c == '\a')
|
||||
{
|
||||
fputs("*ring*\n", stderr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (c == '\n')
|
||||
uart_putchar('\r', stream);
|
||||
loop_until_bit_is_set(UCSRA, UDRE);
|
||||
UDR = c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a character from the UART Rx.
|
||||
*
|
||||
* This features a simple line-editor that allows to delete and
|
||||
* re-edit the characters entered, until either CR or NL is entered.
|
||||
* Printable characters entered will be echoed using uart_putchar().
|
||||
*
|
||||
* Editing characters:
|
||||
*
|
||||
* . \b (BS) or \177 (DEL) delete the previous character
|
||||
* . ^u kills the entire input buffer
|
||||
* . ^w deletes the previous word
|
||||
* . ^r sends a CR, and then reprints the buffer
|
||||
* . \t will be replaced by a single space
|
||||
*
|
||||
* All other control characters will be ignored.
|
||||
*
|
||||
* The internal line buffer is RX_BUFSIZE (80) characters long, which
|
||||
* includes the terminating \n (but no terminating \0). If the buffer
|
||||
* is full (i. e., at RX_BUFSIZE-1 characters in order to keep space for
|
||||
* the trailing \n), any further input attempts will send a \a to
|
||||
* uart_putchar() (BEL character), although line editing is still
|
||||
* allowed.
|
||||
*
|
||||
* Input errors while talking to the UART will cause an immediate
|
||||
* return of -1 (error indication). Notably, this will be caused by a
|
||||
* framing error (e. g. serial line "break" condition), by an input
|
||||
* overrun, and by a parity error (if parity was enabled and automatic
|
||||
* parity recognition is supported by hardware).
|
||||
*
|
||||
* Successive calls to uart_getchar() will be satisfied from the
|
||||
* internal buffer until that buffer is emptied again.
|
||||
*/
|
||||
int
|
||||
uart_getchar(FILE *stream)
|
||||
{
|
||||
uint8_t c;
|
||||
char *cp, *cp2;
|
||||
static char b[RX_BUFSIZE];
|
||||
static char *rxp;
|
||||
|
||||
if (rxp == 0)
|
||||
for (cp = b;;)
|
||||
{
|
||||
loop_until_bit_is_set(UCSRA, RXC);
|
||||
if (UCSRA & _BV(FE))
|
||||
return _FDEV_EOF;
|
||||
if (UCSRA & _BV(DOR))
|
||||
return _FDEV_ERR;
|
||||
c = UDR;
|
||||
/* behaviour similar to Unix stty ICRNL */
|
||||
if (c == '\r')
|
||||
c = '\n';
|
||||
if (c == '\n')
|
||||
{
|
||||
*cp = c;
|
||||
uart_putchar(c, stream);
|
||||
rxp = b;
|
||||
break;
|
||||
}
|
||||
else if (c == '\t')
|
||||
c = ' ';
|
||||
|
||||
if ((c >= (uint8_t)' ' && c <= (uint8_t)'\x7e') ||
|
||||
c >= (uint8_t)'\xa0')
|
||||
{
|
||||
if (cp == b + RX_BUFSIZE - 1)
|
||||
uart_putchar('\a', stream);
|
||||
else
|
||||
{
|
||||
*cp++ = c;
|
||||
uart_putchar(c, stream);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'c' & 0x1f:
|
||||
return -1;
|
||||
|
||||
case '\b':
|
||||
case '\x7f':
|
||||
if (cp > b)
|
||||
{
|
||||
uart_putchar('\b', stream);
|
||||
uart_putchar(' ', stream);
|
||||
uart_putchar('\b', stream);
|
||||
cp--;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r' & 0x1f:
|
||||
uart_putchar('\r', stream);
|
||||
for (cp2 = b; cp2 < cp; cp2++)
|
||||
uart_putchar(*cp2, stream);
|
||||
break;
|
||||
|
||||
case 'u' & 0x1f:
|
||||
while (cp > b)
|
||||
{
|
||||
uart_putchar('\b', stream);
|
||||
uart_putchar(' ', stream);
|
||||
uart_putchar('\b', stream);
|
||||
cp--;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'w' & 0x1f:
|
||||
while (cp > b && cp[-1] != ' ')
|
||||
{
|
||||
uart_putchar('\b', stream);
|
||||
uart_putchar(' ', stream);
|
||||
uart_putchar('\b', stream);
|
||||
cp--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
c = *rxp++;
|
||||
if (c == '\n')
|
||||
rxp = 0;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <joerg@FreeBSD.ORG> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Stdio demo, UART declarations
|
||||
*
|
||||
* $Id: uart.h,v 1.1 2005/12/28 21:38:59 joerg_wunsch Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Perform UART startup initialization.
|
||||
*/
|
||||
void uart_init(void);
|
||||
|
||||
/*
|
||||
* Send one character to the UART.
|
||||
*/
|
||||
int uart_putchar(char c, FILE *stream);
|
||||
|
||||
/*
|
||||
* Size of internal line buffer used by uart_getchar().
|
||||
*/
|
||||
#define RX_BUFSIZE 80
|
||||
|
||||
/*
|
||||
* Receive one character from the UART. The actual reception is
|
||||
* line-buffered, and one character is returned from the buffer at
|
||||
* each invokation.
|
||||
*/
|
||||
int uart_getchar(FILE *stream);
|
Reference in a new issue