changeset 0:a0ce8ebf2f18

LED on PINB0 & PINB1 and UART testing. - LED flasing on PINB0 & PINB1. - print 'hello' messages to UART for every flashing round.
author Thinker K.F. Li <thinker@branda.to>
date Sat, 21 Feb 2009 15:49:59 +0800
parents
children f7c60e525801
files include/avriotools.h src/avriotools.c tests/ledtest.c
diffstat 3 files changed, 182 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/avriotools.h	Sat Feb 21 15:49:59 2009 +0800
@@ -0,0 +1,65 @@
+#ifndef __AVRIOTOOLS_H_
+#define __AVRIOTOOLS_H_
+#include <stdint.h>
+#include <avr/io.h>
+
+typedef enum {PM_INPUT, PM_OUTPUT} pin_mode_t;
+
+extern int pin_mode(volatile uint8_t * port, int pin, pin_mode_t mode);
+#define pin_hi(port, pin) do { port |= _BV(pin); } while(0)
+#define pin_lo(port, pin) do { port &= ~_BV(pin); } while(0)
+
+
+#define UBRRH UBRR0L
+#define UBRRL UBRR0L
+#define UCSRA UCSR0A
+#define U2X U2X0
+#define UDRE UDRE0
+#define UDR UDR0
+#define RXC RXC0
+#define FE FE0
+#define DOR DOR0
+
+extern int uart_init(uint32_t baud);
+#define uart_getc(c)				\
+    do {					\
+	loop_until_bit_is_set(UCSRA, RXC);	\
+	if (UCSRA & _BV(FE))			\
+	    continue;				\
+	if (UCSRA & _BV(DOR))			\
+	    continue;				\
+	c = UDR;				\
+    } while(0)
+/*
+ * c == -1 if not data been read.
+ * \note c must be an integer.
+ */
+#define uart_getc_nowait(c)			\
+    do {					\
+	c = -1;					\
+	if(bit_is_clear(UCSRA, RXC)) break;	\
+	if (UCSRA & _BV(FE))			\
+	    break;				\
+	if (UCSRA & _BV(DOR))			\
+	    break;				\
+	c = UDR;				\
+    } while(0)
+#define uart_putc(c)				\
+    do {					\
+	loop_until_bit_is_set(UCSRA, UDRE);	\
+	UDR = ((uint8_t)(c & 0xff));		\
+    } while(0)
+/*
+ * c == -1 if it been wrote out.
+ * \note c must be an integer.
+ */
+#define uart_putc_nowait(c)			\
+    do {					\
+	if(bit_is_clear(UCSRA, UDRE))		\
+	    break;				\
+	UDR = ((uint8_t)(c & 0xff));		\
+	c = -1;					\
+    } while(0)
+
+
+#endif /* __AVRIOTOOLS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/avriotools.c	Sat Feb 21 15:49:59 2009 +0800
@@ -0,0 +1,76 @@
+#include "avriotools.h"
+#include <avr/io.h>
+
+typedef struct _port_regs {
+    volatile uint8_t *port, *ddr, *pin;
+} port_regs_t;
+
+static port_regs_t regs[] = {
+    { &PORTB, &DDRB, &PINB },
+    { &PORTD, &DDRD, &PIND }
+};
+#define NPORTS (sizeof(regs) / sizeof(*regs))
+
+#define ERR -1
+#define OK 0
+
+int pin_mode(volatile uint8_t * port, int pin, pin_mode_t mode) {
+    port_regs_t *preg;
+    int i;
+
+    for(i = 0; i < NPORTS; i++) {
+	preg = regs + i;
+	if(preg->port == port)
+	    break;
+    }
+    if(i == NPORTS)
+	return ERR;
+
+    switch(mode) {
+    case PM_INPUT:
+	*preg->ddr &= ~_BV(pin);
+	*preg->port |= _BV(pin);
+	break;
+	
+    case PM_OUTPUT:
+	*preg->ddr |=  _BV(pin);
+	break;
+	
+    default:
+	return ERR;
+    }
+
+    return OK;
+}
+
+/* To make setbaud.h no more complaint */
+#define BAUD 9600
+#include <util/setbaud.h>
+
+int uart_init(uint32_t baud) {
+    unsigned long ubrr_v;
+    long err;
+
+    if(baud > (F_CPU / 8))
+	return ERR;
+
+#define F_CPUx2 (F_CPU * 2UL)
+
+    ubrr_v = (F_CPU + baud * 8UL) / (baud * 16UL) - 1UL;
+    /* Allow bias of baud rate in 2%, or use U2X clock.
+     * ATmega168 divides baud rate generator clock by 2, 8, or 16.
+     * Setting U2X bit makes the clock divided by 8 instead of 16.
+     * It makes more accurately output and higher max baud rate.
+     */
+    err = 16L * 100L * (ubrr_v + 1) * baud - F_CPU * 100L;
+    if(err > F_CPUx2 || err < -F_CPUx2 || ubrr_v < 2) {
+	ubrr_v = (F_CPU + baud * 4UL) / (baud * 8UL) - 1UL;
+	UCSRA |= (1 << U2X);
+    } else {
+	UCSRA &= ~(1 << U2X);
+    }
+    
+    UBRRH = ubrr_v >> 8;
+    UBRRL = ubrr_v & 0xff;
+    return OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/ledtest.c	Sat Feb 21 15:49:59 2009 +0800
@@ -0,0 +1,41 @@
+#include <stdio.h>
+#include "avriotools.h"
+#include <util/delay.h>
+#include <avr/io.h>
+
+int main(int argc, char *const argv[]) {
+    int i, cnt = 0;
+    const char *msg = "hello%d\n";
+    char buf[64];
+    
+    uart_init(400000);
+    
+    pin_mode(&PORTB, PINB0, PM_OUTPUT);
+    pin_mode(&PORTB, PINB1, PM_OUTPUT);
+    pin_lo(PORTB, PINB1);
+    for(i = 0; i < 30; i++) {
+	pin_hi(PORTB, PINB0);
+	_delay_ms(100);
+	pin_lo(PORTB, PINB0);
+	_delay_ms(100);
+    }
+    
+    while(1) {
+	pin_hi(PORTB, PINB0);
+	_delay_ms(100);
+	pin_lo(PORTB, PINB0);
+	_delay_ms(100);
+	pin_hi(PORTB, PINB0);
+	_delay_ms(100);
+	pin_lo(PORTB, PINB0);
+	_delay_ms(100);
+	pin_hi(PORTB, PINB0);
+	_delay_ms(500);
+	pin_lo(PORTB, PINB0);
+	_delay_ms(100);
+	
+	sprintf(buf, msg, cnt++);
+	for(i = 0; buf[i] != 0; i++)
+	    uart_putc(buf[i]);
+    }
+}