From 1e7bd86fab311641d7487581aec7c6d11abac244 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 8 Dec 2009 14:16:56 +1100 Subject: [PATCH] Added battery_charger and freq_counter --- battery_charger/Makefile | 75 ++ battery_charger/adc.c | 56 + battery_charger/adc.h | 23 + battery_charger/battery_charger.c | 69 + battery_charger/lcd.c | 595 +++++++++ battery_charger/lcd.h | 263 ++++ battery_charger/ld.strace | 282 ++++ battery_charger/ringbuffer.c | 89 ++ battery_charger/ringbuffer.h | 26 + battery_charger/serial.c | 72 + battery_charger/serial.h | 24 + freq-counter/Makefile | 52 + freq-counter/freq-counter.c | 109 ++ freq-counter/lcd.c | 595 +++++++++ freq-counter/lcd.h | 263 ++++ freq-counter/lcdlibrary.zip | Bin 0 -> 22339 bytes freq-counter/lcdlibrary/doxygen.css | 49 + freq-counter/lcdlibrary/doxygen.png | Bin 0 -> 1281 bytes .../lcdlibrary/group__pfleury__lcd.html | 1174 +++++++++++++++++ freq-counter/lcdlibrary/lcd.c | 609 +++++++++ freq-counter/lcdlibrary/lcd.h | 265 ++++ freq-counter/lcdlibrary/makefile | 425 ++++++ freq-counter/lcdlibrary/test_lcd.c | 167 +++ freq-counter/ringbuffer.c | 89 ++ freq-counter/ringbuffer.h | 26 + freq-counter/serial.c | 72 + freq-counter/serial.h | 24 + freq-counter/uartlibrary.zip | Bin 0 -> 17999 bytes freq-counter/uartlibrary/doxygen.css | 49 + freq-counter/uartlibrary/doxygen.png | Bin 0 -> 1281 bytes .../uartlibrary/group__pfleury__uart.html | 560 ++++++++ freq-counter/uartlibrary/makefile | 508 +++++++ freq-counter/uartlibrary/test_uart.c | 130 ++ freq-counter/uartlibrary/uart.c | 651 +++++++++ freq-counter/uartlibrary/uart.h | 194 +++ 35 files changed, 7585 insertions(+) create mode 100644 battery_charger/Makefile create mode 100644 battery_charger/adc.c create mode 100644 battery_charger/adc.h create mode 100644 battery_charger/battery_charger.c create mode 100644 battery_charger/lcd.c create mode 100644 battery_charger/lcd.h create mode 100644 battery_charger/ld.strace create mode 100644 battery_charger/ringbuffer.c create mode 100644 battery_charger/ringbuffer.h create mode 100644 battery_charger/serial.c create mode 100644 battery_charger/serial.h create mode 100644 freq-counter/Makefile create mode 100644 freq-counter/freq-counter.c create mode 100644 freq-counter/lcd.c create mode 100644 freq-counter/lcd.h create mode 100644 freq-counter/lcdlibrary.zip create mode 100644 freq-counter/lcdlibrary/doxygen.css create mode 100644 freq-counter/lcdlibrary/doxygen.png create mode 100644 freq-counter/lcdlibrary/group__pfleury__lcd.html create mode 100644 freq-counter/lcdlibrary/lcd.c create mode 100644 freq-counter/lcdlibrary/lcd.h create mode 100644 freq-counter/lcdlibrary/makefile create mode 100644 freq-counter/lcdlibrary/test_lcd.c create mode 100644 freq-counter/ringbuffer.c create mode 100644 freq-counter/ringbuffer.h create mode 100644 freq-counter/serial.c create mode 100644 freq-counter/serial.h create mode 100644 freq-counter/uartlibrary.zip create mode 100644 freq-counter/uartlibrary/doxygen.css create mode 100644 freq-counter/uartlibrary/doxygen.png create mode 100644 freq-counter/uartlibrary/group__pfleury__uart.html create mode 100644 freq-counter/uartlibrary/makefile create mode 100644 freq-counter/uartlibrary/test_uart.c create mode 100644 freq-counter/uartlibrary/uart.c create mode 100644 freq-counter/uartlibrary/uart.h diff --git a/battery_charger/Makefile b/battery_charger/Makefile new file mode 100644 index 0000000..16d9084 --- /dev/null +++ b/battery_charger/Makefile @@ -0,0 +1,75 @@ +############################################################################## +# # +# AVR-GCC skeleton # +# # +# by Triffid Hunter # +# # +############################################################################## + +############################################################################## +# # +# Change these to suit your application # +# # +############################################################################## + +PROGRAM = battery_charger + +SOURCES = $(PROGRAM).c ringbuffer.c serial.c lcd.c adc.c + +############################################################################## +# # +# Change these to suit your hardware # +# # +############################################################################## + +MCU_TARGET = atmega168 +F_CPU = 16000000L + +############################################################################## +# # +# These defaults should be ok, change if you need to # +# # +############################################################################## + +ARCH = avr- +OPTIMIZE = -Os +CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(F_CPU) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +LDFLAGS = -Wl,-u,vfprintf -lprintf_min + +CC = $(ARCH)gcc +OBJDUMP = $(ARCH)objdump +OBJCOPY = $(ARCH)objcopy +AVRDUDE = ~/bin/avrdude + +PROGPORT = /dev/arduino +PROGBAUD = 19200 + +OBJ = $(patsubst %.c,%.o,${SOURCES}) + +.PHONY: all program clean +.PRECIOUS: %.o %.elf + +all: $(PROGRAM).hex $(PROGRAM).lst + +program: $(PROGRAM).hex + stty $(PROGBAUD) raw ignbrk hup < $(PROGPORT) + $(AVRDUDE) -cstk500v1 -b$(PROGBAUD) -p$(MCU_TARGET) -P$(PROGPORT) -C/etc/avrdude.conf -U flash:w:$^ + stty -hup -echo < $(PROGPORT) + +clean: + rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al + +%.o: %.c + $(CC) -c $(CFLAGS) -Wa,-adhlns=$(<:.c=.al) -o $@ $^ + +%.elf: $(OBJ) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + +%.lst: %.elf + $(OBJDUMP) -h -S $< > $@ + +%.hex: %.elf + $(OBJCOPY) -j .text -j .data -O ihex $< $@ + +%.bin: %.elf + $(OBJCOPY) -j .text -j .data -O binary $< $@ diff --git a/battery_charger/adc.c b/battery_charger/adc.c new file mode 100644 index 0000000..63a1f8a --- /dev/null +++ b/battery_charger/adc.c @@ -0,0 +1,56 @@ +#include "adc.h" + +void adc_init(uint8_t vsel) +{ + PRR &= ~_BV(PRADC); + ADMUX = (ADMUX & ~(_BV(REFS1) | _BV(REFS0))) | vsel; + ADCSRA = _BV(ADEN); + + #if F_CPU >= (ADC_MAX_FREQ * 128) + #error F_CPU is too high for ADC prescaler! + #elif F_CPU >= (ADC_MAX_FREQ * 64) + ADCSRA |= _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); + #elif F_CPU >= (ADC_MAX_FREQ * 32) + ADCSRA |= _BV(ADPS2) | _BV(ADPS1); + #elif F_CPU >= (ADC_MAX_FREQ * 16) + ADCSRA |= _BV(ADPS2) | _BV(ADPS0); + #elif F_CPU >= (ADC_MAX_FREQ * 8) + ADCSRA |= _BV(ADPS2); + #elif F_CPU >= (ADC_MAX_FREQ * 4) + ADCSRA |= _BV(ADPS1) | _BV(ADPS0); + #elif F_CPU >= (ADC_MAX_FREQ * 2) + ADCSRA |= _BV(ADPS1); + #elif F_CPU >= (ADC_MAX_FREQ >> 1) + ADSRA |= _BV(ADPS0); + #else + #error F_CPU is too slow for ADC to run well! + #endif +} + +uint16_t adc_read(uint8_t pin) +{ + adc_start(pin); + adc_wait(); + return adc_result(); +} + +void adc_start(uint8_t pin) +{ + ADMUX = (ADMUX & 0xF0) | pin; + ADCSRA |= _BV(ADSC); +} + +uint16_t adc_result() +{ + return ADC; +} + +uint8_t adc_finished() +{ + return (ADCSRA & _BV(ADSC))?0xFF:0; +} + +void adc_wait() +{ + for (;adc_finished() == 0;); +} diff --git a/battery_charger/adc.h b/battery_charger/adc.h new file mode 100644 index 0000000..1a96120 --- /dev/null +++ b/battery_charger/adc.h @@ -0,0 +1,23 @@ +#ifndef _ADC_H +#define _ADC_H + +#include +#include + +#define VSEL_AREF 0 +#define VSEL_AVCC _BV(REFS0) +#define VSEL_1V1 _BV(REFS1) + +#define ADC_MAX_FREQ 200000 + +void adc_init(uint8_t vsel); + +uint16_t adc_read(uint8_t pin); + +void adc_start(uint8_t pin); +inline uint16_t adc_result(void); + +uint8_t adc_finished(void); +void adc_wait(void); + +#endif /* _ADC_H */ diff --git a/battery_charger/battery_charger.c b/battery_charger/battery_charger.c new file mode 100644 index 0000000..f20035e --- /dev/null +++ b/battery_charger/battery_charger.c @@ -0,0 +1,69 @@ +#include +#include +#include + +#include +#include + +#include "serial.h" +#include "lcd.h" + +// write to lcd function for fdev_setup_stream +static int lcd_putc_fdev(char c, FILE *stream) +{ + lcd_putc(c); + return 0; +} + +int serial_putc_fdev(char c, FILE *stream) +{ + serial_writechar((uint8_t) c); + return 0; +} + +int serial_getc_fdev(FILE *stream) +{ + for (;serial_rxchars() == 0;); + return (int) serial_popchar(); +} + +static FILE lcdo = FDEV_SETUP_STREAM(lcd_putc_fdev, NULL, _FDEV_SETUP_WRITE); +static FILE serio = FDEV_SETUP_STREAM(serial_putc_fdev, serial_getc_fdev, _FDEV_SETUP_RW); + +int main (void) +{ + // set up LCD + lcd_init(LCD_DISP_ON_CURSOR); + + lcd_puts_P("Starting..."); + + // set up STDIN/OUT/ERR + stdin = &serio; + stdout = &lcdo; + stderr = &lcdo; + + // set up serial + serial_init(19200); + + sei(); + + lcd_gotoxy(0, 0); + fprintf(&lcdo, "Battery Charger OK"); + + for (;;) + { + # switch off all currents + # check battery presence + # for (each battery) { + # check ambient temperature + # check battery temperature + # calculate delta T + # check battery voltage + # calculate delta V + # check charge cycle location + # apply suitable current + # update screen/indicators + # } + # wait + } +} diff --git a/battery_charger/lcd.c b/battery_charger/lcd.c new file mode 100644 index 0000000..1505eff --- /dev/null +++ b/battery_charger/lcd.c @@ -0,0 +1,595 @@ +/**************************************************************************** + Title : HD44780U LCD library + Author: Peter Fleury http://jump.to/fleury + File: $Id: lcd.c,v 1.14.2.1 2006/01/29 12:16:41 peter Exp $ + Software: AVR-GCC 3.3 + Target: any AVR device, memory mapped mode only for AT90S4414/8515/Mega + + DESCRIPTION + Basic routines for interfacing a HD44780U-based text lcd display + + Originally based on Volker Oth's lcd library, + changed lcd_init(), added additional constants for lcd_command(), + added 4-bit I/O mode, improved and optimized code. + + Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in + 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported. + + Memory mapped mode compatible with Kanda STK200, but supports also + generation of R/W signal through A8 address line. + + USAGE + See the C include lcd.h file for a description of each function + +*****************************************************************************/ +#include +#include +#include +#include "lcd.h" + + + +/* +** constants/macros +*/ +#define DDR(x) (*(&x - 1)) /* address of data direction register of port x */ +#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) + /* on ATmega64/128 PINF is on port 0x00 and not 0x60 */ + #define PIN(x) ( &PORTF==&(x) ? _SFR_IO8(0x00) : (*(&x - 2)) ) +#else + #define PIN(x) (*(&x - 2)) /* address of input register of port x */ +#endif + + +#if LCD_IO_MODE + #define lcd_e_delay() __asm__ __volatile__( "rjmp 1f\n 1:" ); + #define lcd_e_high() LCD_E_PORT |= _BV(LCD_E_PIN); + #define lcd_e_low() LCD_E_PORT &= ~_BV(LCD_E_PIN); + #define lcd_e_toggle() toggle_e() + #define lcd_rw_high() LCD_RW_PORT |= _BV(LCD_RW_PIN) + #define lcd_rw_low() LCD_RW_PORT &= ~_BV(LCD_RW_PIN) + #define lcd_rs_high() LCD_RS_PORT |= _BV(LCD_RS_PIN) + #define lcd_rs_low() LCD_RS_PORT &= ~_BV(LCD_RS_PIN) +#endif + +#if LCD_IO_MODE + #if LCD_LINES==1 + #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE + #else + #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES + #endif +#else + #if LCD_LINES==1 + #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_1LINE + #else + #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_2LINES + #endif +#endif + +#if LCD_CONTROLLER_KS0073 + #if LCD_LINES==4 + #define KS0073_EXTENDED_FUNCTION_REGISTER_ON 0x24 /* |0|010|0100 4-bit mode extension-bit RE = 1 */ + #define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x20 /* |0|000|1001 4 lines mode */ + #define KS0073_4LINES_MODE 0x09 /* |0|001|0000 4-bit mode, extension-bit RE = 0 */ + #endif +#endif + +/* +** function prototypes +*/ +#if LCD_IO_MODE +static void toggle_e(void); +#endif + +/* +** local functions +*/ + + + +/************************************************************************* + delay loop for small accurate delays: 16-bit counter, 4 cycles/loop +*************************************************************************/ +static inline void _delayFourCycles(unsigned int __count) +{ + if ( __count == 0 ) + __asm__ __volatile__( "rjmp 1f\n 1:" ); // 2 cycles + else + __asm__ __volatile__ ( + "1: sbiw %0,1" "\n\t" + "brne 1b" // 4 cycles/loop + : "=w" (__count) + : "0" (__count) + ); +} + + +/************************************************************************* +delay for a minimum of microseconds +the number of loops is calculated at compile-time from MCU clock frequency +*************************************************************************/ +#define delay(us) _delayFourCycles( ( ( 1*(XTAL/4000) )*us)/1000 ) + + +#if LCD_IO_MODE +/* toggle Enable Pin to initiate write */ +static void toggle_e(void) +{ + lcd_e_high(); + lcd_e_delay(); + lcd_e_low(); +} +#endif + + +/************************************************************************* +Low-level function to write byte to LCD controller +Input: data byte to write to LCD + rs 1: write data + 0: write instruction +Returns: none +*************************************************************************/ +#if LCD_IO_MODE +static void lcd_write(uint8_t data,uint8_t rs) +{ + if (rs) { /* write data (RS=1, RW=0) */ + lcd_rs_high(); + } else { /* write instruction (RS=0, RW=0) */ + lcd_rs_low(); + } + lcd_rw_low(); + + if ( + (&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) + && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) + ) + { + /* configure data pins as output */ + DDR(LCD_DATA0_PORT) |= 0x0F; + + /* output high nibble first */ + LCD_DATA0_PORT = (LCD_DATA0_PORT & 0xF0) | ((data >> 4) & 0x0F); + lcd_e_toggle(); + + /* output low nibble */ + LCD_DATA0_PORT = (LCD_DATA0_PORT & 0xF0) | (data & 0x0F); + lcd_e_toggle(); + + /* all data pins high (inactive) */ + LCD_DATA0_PORT = (LCD_DATA0_PORT & 0xF0) | 0x0F; + } + else + { + /* configure data pins as output */ + DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); + DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); + DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); + DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); + + /* output high nibble first */ + LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); + LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); + LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); + if(data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + if(data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + if(data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + if(data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + lcd_e_toggle(); + + /* output low nibble */ + LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); + LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); + LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); + if(data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + if(data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + if(data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + if(data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + lcd_e_toggle(); + + /* all data pins high (inactive) */ + LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + } +} +#else +#define lcd_write(d,rs) if (rs) *(volatile uint8_t*)(LCD_IO_DATA) = d; else *(volatile uint8_t*)(LCD_IO_FUNCTION) = d; +/* rs==0 -> write instruction to LCD_IO_FUNCTION */ +/* rs==1 -> write data to LCD_IO_DATA */ +#endif + + +/************************************************************************* +Low-level function to read byte from LCD controller +Input: rs 1: read data + 0: read busy flag / address counter +Returns: byte read from LCD controller +*************************************************************************/ +#if LCD_IO_MODE +static uint8_t lcd_read(uint8_t rs) +{ + uint8_t data; + + if (rs) + lcd_rs_high(); /* RS=1: read data */ + else + lcd_rs_low(); /* RS=0: read busy flag */ + lcd_rw_high(); /* RW=1 read mode */ + + if ( + (&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) + && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) + ) + { + DDR(LCD_DATA0_PORT) &= 0xF0; /* configure data pins as input */ + + lcd_e_high(); + lcd_e_delay(); + data = PIN(LCD_DATA0_PORT) << 4; /* read high nibble first */ + lcd_e_low(); + + lcd_e_delay(); /* Enable 500ns low */ + + lcd_e_high(); + lcd_e_delay(); + data |= PIN(LCD_DATA0_PORT) & 0x0F; /* read low nibble */ + lcd_e_low(); + } + else + { + /* configure data pins as input */ + DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN); + DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN); + DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN); + DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN); + + /* read high nibble first */ + lcd_e_high(); + lcd_e_delay(); + data = 0; + if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x10; + if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x20; + if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x40; + if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x80; + lcd_e_low(); + + lcd_e_delay(); /* Enable 500ns low */ + + /* read low nibble */ + lcd_e_high(); + lcd_e_delay(); + if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x01; + if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x02; + if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x04; + if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x08; + lcd_e_low(); + } + return data; +} +#else +#define lcd_read(rs) (rs) ? *(volatile uint8_t*)(LCD_IO_DATA+LCD_IO_READ) : *(volatile uint8_t*)(LCD_IO_FUNCTION+LCD_IO_READ) +/* rs==0 -> read instruction from LCD_IO_FUNCTION */ +/* rs==1 -> read data from LCD_IO_DATA */ +#endif + + +/************************************************************************* +loops while lcd is busy, returns address counter +*************************************************************************/ +static uint8_t lcd_waitbusy(void) +{ + /* wait until busy flag is cleared */ + for (; lcd_read(0) & (1 << LCD_BUSY); ); + + /* the address counter is updated 4us after the busy flag is cleared */ + delay(2); + + /* now read the address counter */ + return (lcd_read(0)); // return address counter +}/* lcd_waitbusy */ + + +/************************************************************************* +Move cursor to the start of next line or to the first line if the cursor +is already on the last line. +*************************************************************************/ +static inline void lcd_newline(uint8_t pos) +{ + register uint8_t addressCounter; + +#if LCD_LINES==1 + addressCounter = 0; +#endif +#if LCD_LINES==2 + if ( pos < (LCD_START_LINE2) ) + addressCounter = LCD_START_LINE2; + else + addressCounter = LCD_START_LINE1; +#endif +#if LCD_LINES==4 +#if KS0073_4LINES_MODE + if ( pos < LCD_START_LINE2 ) + addressCounter = LCD_START_LINE2; + else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3) ) + addressCounter = LCD_START_LINE3; + else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4) ) + addressCounter = LCD_START_LINE4; + else + addressCounter = LCD_START_LINE1; +#else + if ( pos < LCD_START_LINE3 ) + addressCounter = LCD_START_LINE2; + else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4) ) + addressCounter = LCD_START_LINE3; + else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) ) + addressCounter = LCD_START_LINE4; + else + addressCounter = LCD_START_LINE1; +#endif +#endif + lcd_command((1 << LCD_DDRAM) + addressCounter); + +}/* lcd_newline */ + + +/* +** PUBLIC FUNCTIONS +*/ + +/************************************************************************* +Send LCD controller instruction command +Input: instruction to send to LCD controller, see HD44780 data sheet +Returns: none +*************************************************************************/ +void lcd_command(uint8_t cmd) +{ + lcd_waitbusy(); + lcd_write(cmd,0); +} + + +/************************************************************************* +Send data byte to LCD controller +Input: data to send to LCD controller, see HD44780 data sheet +Returns: none +*************************************************************************/ +void lcd_data(uint8_t data) +{ + lcd_waitbusy(); + lcd_write(data,1); +} + + + +/************************************************************************* +Set cursor to specified position +Input: x horizontal position (0: left most position) + y vertical position (0: first line) +Returns: none +*************************************************************************/ +void lcd_gotoxy(uint8_t x, uint8_t y) +{ +#if LCD_LINES==1 + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); +#endif +#if LCD_LINES==2 + if ( y==0 ) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); + else + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x); +#endif +#if LCD_LINES==4 + if ( y==0 ) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); + else if ( y==1) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x); + else if ( y==2) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE3 + x); + else /* y==3 */ + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE4 + x); +#endif + +}/* lcd_gotoxy */ + + +/************************************************************************* +*************************************************************************/ +int lcd_getxy(void) +{ + return lcd_waitbusy(); +} + + +/************************************************************************* +Clear display and set cursor to home position +*************************************************************************/ +void lcd_clrscr(void) +{ + lcd_command(1 << LCD_CLR); +} + + +/************************************************************************* +Set cursor to home position +*************************************************************************/ +void lcd_home(void) +{ + lcd_command(1 << LCD_HOME); +} + + +/************************************************************************* +Display character at current cursor position +Input: character to be displayed +Returns: none +*************************************************************************/ +void lcd_putc(char c) +{ + uint8_t pos; + + pos = lcd_waitbusy(); // read busy-flag and address counter + if (c=='\n') + lcd_newline(pos); + else + { +#if LCD_WRAP_LINES==1 +#if LCD_LINES==1 + if ( pos == LCD_START_LINE1 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1,0); +#elif LCD_LINES==2 + if ( pos == LCD_START_LINE1 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2,0); + else if ( pos == LCD_START_LINE2 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1,0); +#elif LCD_LINES==4 + if ( pos == LCD_START_LINE1 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2,0); + else if ( pos == LCD_START_LINE2 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE3,0); + else if ( pos == LCD_START_LINE3 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE4,0); + else if ( pos == LCD_START_LINE4 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1,0); +#endif + lcd_waitbusy(); +#endif + lcd_write(c, 1); + } + +}/* lcd_putc */ + + +/************************************************************************* +Display string without auto linefeed +Input: string to be displayed +Returns: none +*************************************************************************/ +void lcd_puts(const char *s) +/* print string on lcd (no auto linefeed) */ +{ + register char c; + + while ( (c = *s++) ) { + lcd_putc(c); + } + +}/* lcd_puts */ + + +/************************************************************************* +Display string from program memory without auto linefeed +Input: string from program memory be be displayed +Returns: none +*************************************************************************/ +void lcd_puts_p(const char *progmem_s) +/* print string from program memory on lcd (no auto linefeed) */ +{ + register char c; + + while ( (c = pgm_read_byte(progmem_s++)) ) { + lcd_putc(c); + } + +}/* lcd_puts_p */ + + +/************************************************************************* +Initialize display and select type of cursor +Input: dispAttr LCD_DISP_OFF display off + LCD_DISP_ON display on, cursor off + LCD_DISP_ON_CURSOR display on, cursor on + LCD_DISP_CURSOR_BLINK display on, cursor on flashing +Returns: none +*************************************************************************/ +void lcd_init(uint8_t dispAttr) +{ +#if LCD_IO_MODE + /* + * Initialize LCD to 4 bit I/O mode + */ + + if ( + ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT ) + && ( &LCD_RS_PORT == &LCD_DATA0_PORT) && ( &LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT) + ) + { + /* configure all port bits as output (all LCD lines on same port) */ + DDR(LCD_DATA0_PORT) |= (1 << LCD_DATA0_PIN) | (1 << LCD_DATA1_PIN) | (1 << LCD_DATA2_PIN) | (1 << LCD_DATA3_PIN) | (1 << LCD_RS_PIN) | (1 << LCD_RW_PIN) | (1 << LCD_E_PIN); + } + else if ( + ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT ) + ) + { + /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */ + DDR(LCD_DATA0_PORT) |= (1 << LCD_DATA0_PIN) | (1 << LCD_DATA1_PIN) | (1 << LCD_DATA2_PIN) | (1 << LCD_DATA3_PIN); + DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); + DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); + DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); + } + else + { + /* configure all port bits as output (LCD data and control lines on different ports */ + DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); + DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); + DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); + DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); + DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); + DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); + DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); + } + delay(16000); /* wait 16ms or more after power-on */ + + /* initial write to lcd is 8bit */ + LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); // _BV(LCD_FUNCTION)>>4; + LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // _BV(LCD_FUNCTION_8BIT)>>4; + lcd_e_toggle(); + delay(4992); /* delay, busy flag can't be checked here */ + + /* repeat last command */ + lcd_e_toggle(); delay(64); /* delay, busy flag can't be checked here */ + + /* repeat last command a third time */ + lcd_e_toggle(); delay(64); /* delay, busy flag can't be checked here */ + + /* now configure for 4bit mode */ + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // LCD_FUNCTION_4BIT_1LINE>>4 + lcd_e_toggle(); + delay(64); /* some displays need this additional delay */ + + /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */ +#else + /* + * Initialize LCD to 8 bit memory mapped mode + */ + + /* enable external SRAM (memory mapped lcd) and one wait state */ + MCUCR = _BV(SRE) | _BV(SRW); + + /* reset LCD */ + delay(16000); /* wait 16ms after power-on */ + lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ + delay(4992); /* wait 5ms */ + lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ + delay(64); /* wait 64us */ + lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ + delay(64); /* wait 64us */ +#endif + +#if KS0073_4LINES_MODE + /* Display with KS0073 controller requires special commands for enabling 4 line mode */ + lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON); + lcd_command(KS0073_4LINES_MODE); + lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF); +#else + lcd_command(LCD_FUNCTION_DEFAULT); /* function set: display lines */ +#endif + + lcd_command(LCD_DISP_OFF); /* display off */ + lcd_clrscr(); /* display clear */ + lcd_command(LCD_MODE_DEFAULT); /* set entry mode */ + lcd_command(dispAttr); /* display/cursor control */ + +}/* lcd_init */ diff --git a/battery_charger/lcd.h b/battery_charger/lcd.h new file mode 100644 index 0000000..bec1cee --- /dev/null +++ b/battery_charger/lcd.h @@ -0,0 +1,263 @@ +#ifndef LCD_H +#define LCD_H +/************************************************************************* + Title : C include file for the HD44780U LCD library (lcd.c) + Author: Peter Fleury http://jump.to/fleury + File: $Id: lcd.h,v 1.13.2.2 2006/01/30 19:51:33 peter Exp $ + Software: AVR-GCC 3.3 + Hardware: any AVR device, memory mapped mode only for AT90S4414/8515/Mega +***************************************************************************/ + +/** + @defgroup pfleury_lcd LCD library + @code #include @endcode + + @brief Basic routines for interfacing a HD44780U-based text LCD display + + Originally based on Volker Oth's LCD library, + changed lcd_init(), added additional constants for lcd_command(), + added 4-bit I/O mode, improved and optimized code. + + Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in + 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported. + + Memory mapped mode compatible with Kanda STK200, but supports also + generation of R/W signal through A8 address line. + + @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury + + @see The chapter Interfacing a HD44780 Based LCD to an AVR + on my home page. + +*/ + +/*@{*/ + +#if (__GNUC__ * 100 + __GNUC_MINOR__) < 303 +#error "This library requires AVR-GCC 3.3 or later, update to newer AVR-GCC compiler !" +#endif + +#include +#include + +/** + * @name Definitions for MCU Clock Frequency + * Adapt the MCU clock frequency in Hz to your target. + */ +#define XTAL F_CPU /**< clock frequency in Hz, used to calculate delay timer */ + +/** + * @name Definition for LCD controller type + * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller. + */ +#define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */ + +/** + * @name Definitions for Display Size + * Change these definitions to adapt setting to your display + */ +#define LCD_LINES 2 /**< number of visible lines of the display */ +#define LCD_DISP_LENGTH 16 /**< visibles characters per line of the display */ +#define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */ +#define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ +#define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ +#define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ +#define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ +#define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */ + +#define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */ + +#if LCD_IO_MODE +/** + * @name Definitions for 4-bit IO mode + * Change LCD_PORT if you want to use a different port for the LCD pins. + * + * The four LCD data lines and the three control lines RS, RW, E can be on the + * same port or on different ports. + * Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on + * different ports. + * + * Normally the four data lines should be mapped to bit 0..3 on one port, but it + * is possible to connect these data lines in different order or even on different + * ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions. + * */ +#define LCD_PORT PORTB /**< port for the LCD lines */ +#define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */ +#define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */ +#define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ +#define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ +#define LCD_DATA0_PIN 0 /**< pin for 4bit data bit 0 */ +#define LCD_DATA1_PIN 1 /**< pin for 4bit data bit 1 */ +#define LCD_DATA2_PIN 2 /**< pin for 4bit data bit 2 */ +#define LCD_DATA3_PIN 3 /**< pin for 4bit data bit 3 */ +#define LCD_RS_PORT PORTD /**< port for RS line */ +#define LCD_RS_PIN 2 /**< pin for RS line */ +#define LCD_RW_PORT PORTD /**< port for RW line */ +#define LCD_RW_PIN 3 /**< pin for RW line */ +#define LCD_E_PORT PORTD /**< port for Enable line */ +#define LCD_E_PIN 4 /**< pin for Enable line */ + +#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || \ + defined(__AVR_ATmega8515__)|| defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || \ + defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__) +/* + * memory mapped mode is only supported when the device has an external data memory interface + */ +#define LCD_IO_DATA 0xC000 /* A15=E=1, A14=RS=1 */ +#define LCD_IO_FUNCTION 0x8000 /* A15=E=1, A14=RS=0 */ +#define LCD_IO_READ 0x0100 /* A8 =R/W=1 (R/W: 1=Read, 0=Write */ +#else +#error "external data memory interface not available for this device, use 4-bit IO port mode" + +#endif + + +/** + * @name Definitions for LCD command instructions + * The constants define the various LCD controller instructions which can be passed to the + * function lcd_command(), see HD44780 data sheet for a complete description. + */ + +/* instruction register bit positions, see HD44780U data sheet */ +#define LCD_CLR 0 /* DB0: clear display */ +#define LCD_HOME 1 /* DB1: return to home position */ +#define LCD_ENTRY_MODE 2 /* DB2: set entry mode */ +#define LCD_ENTRY_INC 1 /* DB1: 1=increment, 0=decrement */ +#define LCD_ENTRY_SHIFT 0 /* DB2: 1=display shift on */ +#define LCD_ON 3 /* DB3: turn lcd/cursor on */ +#define LCD_ON_DISPLAY 2 /* DB2: turn display on */ +#define LCD_ON_CURSOR 1 /* DB1: turn cursor on */ +#define LCD_ON_BLINK 0 /* DB0: blinking cursor ? */ +#define LCD_MOVE 4 /* DB4: move cursor/display */ +#define LCD_MOVE_DISP 3 /* DB3: move display (0-> cursor) ? */ +#define LCD_MOVE_RIGHT 2 /* DB2: move right (0-> left) ? */ +#define LCD_FUNCTION 5 /* DB5: function set */ +#define LCD_FUNCTION_8BIT 4 /* DB4: set 8BIT mode (0->4BIT mode) */ +#define LCD_FUNCTION_2LINES 3 /* DB3: two lines (0->one line) */ +#define LCD_FUNCTION_10DOTS 2 /* DB2: 5x10 font (0->5x7 font) */ +#define LCD_CGRAM 6 /* DB6: set CG RAM address */ +#define LCD_DDRAM 7 /* DB7: set DD RAM address */ +#define LCD_BUSY 7 /* DB7: LCD is busy */ + +/* set entry mode: display shift on/off, dec/inc cursor move direction */ +#define LCD_ENTRY_DEC 0x04 /* display shift off, dec cursor move dir */ +#define LCD_ENTRY_DEC_SHIFT 0x05 /* display shift on, dec cursor move dir */ +#define LCD_ENTRY_INC_ 0x06 /* display shift off, inc cursor move dir */ +#define LCD_ENTRY_INC_SHIFT 0x07 /* display shift on, inc cursor move dir */ + +/* display on/off, cursor on/off, blinking char at cursor position */ +#define LCD_DISP_OFF 0x08 /* display off */ +#define LCD_DISP_ON 0x0C /* display on, cursor off */ +#define LCD_DISP_ON_BLINK 0x0D /* display on, cursor off, blink char */ +#define LCD_DISP_ON_CURSOR 0x0E /* display on, cursor on */ +#define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char */ + +/* move cursor/shift display */ +#define LCD_MOVE_CURSOR_LEFT 0x10 /* move cursor left (decrement) */ +#define LCD_MOVE_CURSOR_RIGHT 0x14 /* move cursor right (increment) */ +#define LCD_MOVE_DISP_LEFT 0x18 /* shift display left */ +#define LCD_MOVE_DISP_RIGHT 0x1C /* shift display right */ + +/* function set: set interface data length and number of display lines */ +#define LCD_FUNCTION_4BIT_1LINE 0x20 /* 4-bit interface, single line, 5x7 dots */ +#define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line, 5x7 dots */ +#define LCD_FUNCTION_8BIT_1LINE 0x30 /* 8-bit interface, single line, 5x7 dots */ +#define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line, 5x7 dots */ + + +#define LCD_MODE_DEFAULT ((1< 6, base_addr:0xb7d956c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 +8870 mprotect(0xb7ed0000, 8192, PROT_READ) = 0 +8870 mprotect(0x804a000, 4096, PROT_READ) = 0 +8870 mprotect(0xb7f0d000, 4096, PROT_READ) = 0 +8870 munmap(0xb7ed7000, 105128) = 0 +8870 brk(0) = 0x9a43000 +8870 brk(0x9a64000) = 0x9a64000 +8870 stat64("/usr/i686-pc-linux-gnu/avr/gcc-bin/4.3.3/avr-gcc", {st_mode=S_IFREG|0755, st_size=196108, ...}) = 0 +8870 execve("/usr/i686-pc-linux-gnu/avr/gcc-bin/4.3.3/avr-gcc", ["/usr/i686-pc-linux-gnu/avr/gcc-b"..., "-g", "-Wall", "-Wstrict-prototypes", "-Os", "-mmcu=atmega168", "-DF_CPU=16000000L", "-std=gnu99", "-funsigned-char", "-funsigned-bitfields", "-fpack-struct", "-fshort-enums", "-Wl,-u,vfprintf", "-lprintf_min", "-o", "battery_charger.elf", ...], [/* 55 vars */]) = 0 +8870 brk(0) = 0x91d7000 +8870 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) +8870 open("/etc/ld.so.cache", O_RDONLY) = 3 +8870 fstat64(3, {st_mode=S_IFREG|0644, st_size=105128, ...}) = 0 +8870 mmap2(NULL, 105128, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7eeb000 +8870 close(3) = 0 +8870 open("/lib/libc.so.6", O_RDONLY) = 3 +8870 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220g\1\0004\0\0\0\244"..., 512) = 512 +8870 fstat64(3, {st_mode=S_IFREG|0755, st_size=1302812, ...}) = 0 +8870 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7eea000 +8870 mmap2(NULL, 1308240, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7daa000 +8870 mmap2(0xb7ee4000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x13a) = 0xb7ee4000 +8870 mmap2(0xb7ee7000, 9808, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7ee7000 +8870 close(3) = 0 +8870 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7da9000 +8870 set_thread_area({entry_number:-1 -> 6, base_addr:0xb7da96c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 +8870 mprotect(0xb7ee4000, 8192, PROT_READ) = 0 +8870 mprotect(0x8077000, 4096, PROT_READ) = 0 +8870 mprotect(0xb7f21000, 4096, PROT_READ) = 0 +8870 munmap(0xb7eeb000, 105128) = 0 +8870 brk(0) = 0x91d7000 +8870 brk(0x91f8000) = 0x91f8000 +8870 rt_sigaction(SIGINT, {0x1, [INT], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 +8870 rt_sigaction(SIGINT, {0x804f730, [INT], SA_RESTART}, {0x1, [INT], SA_RESTART}, 8) = 0 +8870 rt_sigaction(SIGHUP, {0x1, [HUP], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 +8870 rt_sigaction(SIGHUP, {0x804f730, [HUP], SA_RESTART}, {0x1, [HUP], SA_RESTART}, 8) = 0 +8870 rt_sigaction(SIGTERM, {0x1, [TERM], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 +8870 rt_sigaction(SIGTERM, {0x804f730, [TERM], SA_RESTART}, {0x1, [TERM], SA_RESTART}, 8) = 0 +8870 rt_sigaction(SIGPIPE, {0x1, [PIPE], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 +8870 rt_sigaction(SIGPIPE, {0x804f730, [PIPE], SA_RESTART}, {0x1, [PIPE], SA_RESTART}, 8) = 0 +8870 rt_sigaction(SIGCHLD, {SIG_DFL, [CHLD], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 +8870 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 lstat64("/usr/i686-pc-linux-gnu", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 lstat64("/usr/i686-pc-linux-gnu/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 lstat64("/usr/i686-pc-linux-gnu/avr/gcc-bin", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 lstat64("/usr/i686-pc-linux-gnu/avr/gcc-bin/4.3.3", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 lstat64("/usr/i686-pc-linux-gnu/avr/gcc-bin/4.3.3/avr-gcc", {st_mode=S_IFREG|0755, st_size=196108, ...}) = 0 +8870 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 lstat64("/usr/i686-pc-linux-gnu", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 lstat64("/usr/i686-pc-linux-gnu/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 lstat64("/usr/i686-pc-linux-gnu/avr/gcc-bin", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 lstat64("/usr/i686-pc-linux-gnu/avr/gcc-bin/4.3.3", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 lstat64("/usr/i686-pc-linux-gnu/avr/gcc-bin/4.3.3/avr-gcc", {st_mode=S_IFREG|0755, st_size=196108, ...}) = 0 +8870 access("/usr/lib/gcc/avr/4.3.3/", X_OK) = 0 +8870 access("/usr/lib/gcc/avr/4.3.3/", X_OK) = 0 +8870 access("battery_charger.o", F_OK) = 0 +8870 access("ringbuffer.o", F_OK) = 0 +8870 access("serial.o", F_OK) = 0 +8870 access("lcd.o", F_OK) = 0 +8870 access("/usr/lib/gcc/avr/4.3.3/specs", R_OK) = -1 ENOENT (No such file or directory) +8870 access("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/avr/4.3.3/specs", R_OK) = -1 ENOENT (No such file or directory) +8870 access("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/specs", R_OK) = -1 ENOENT (No such file or directory) +8870 access("/usr/lib/gcc/avr/specs", R_OK) = -1 ENOENT (No such file or directory) +8870 stat64("/usr/libexec/gcc/avr/4.3.3/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/libexec/gcc/avr/4.3.3/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/libexec/gcc/avr/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/lib/gcc/avr/4.3.3/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/lib/gcc/avr/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/lib/gcc/avr/4.3.3/../../../../avr/bin/avr/4.3.3/.", 0xbfc20ca4) = -1 ENOENT (No such file or directory) +8870 stat64("/usr/lib/gcc/avr/4.3.3/../../../../avr/bin/.", 0xbfc20cb4) = -1 ENOENT (No such file or directory) +8870 stat64("/usr/lib/gcc/avr/4.3.3/avr5/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/avr/4.3.3/avr5/.", 0xbfc20ca4) = -1 ENOENT (No such file or directory) +8870 stat64("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/lib/gcc/avr/4.3.3/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/avr/4.3.3/.", 0xbfc20ca4) = -1 ENOENT (No such file or directory) +8870 stat64("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 access("/usr/lib/gcc/avr/4.3.3/avr5/crtm168.o", R_OK) = -1 ENOENT (No such file or directory) +8870 access("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/avr/4.3.3/avr5/crtm168.o", R_OK) = -1 ENOENT (No such file or directory) +8870 access("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/crtm168.o", R_OK) = 0 +8870 stat64("/usr/lib/gcc/avr/4.3.3/avr5/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/avr/4.3.3/avr5/.", 0xbfc20054) = -1 ENOENT (No such file or directory) +8870 stat64("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/lib/gcc/avr/4.3.3/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/avr/4.3.3/.", 0xbfc20054) = -1 ENOENT (No such file or directory) +8870 stat64("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8870 stat64("/usr/libexec/gcc/avr/4.3.3/ld", 0xbfc20c84) = -1 ENOENT (No such file or directory) +8870 stat64("/usr/libexec/gcc/avr/4.3.3/ld", 0xbfc20c84) = -1 ENOENT (No such file or directory) +8870 stat64("/usr/libexec/gcc/avr/ld", {st_mode=S_IFREG|0755, st_size=349460, ...}) = 0 +8870 access("/usr/libexec/gcc/avr/ld", X_OK) = 0 +8870 vfork() = 8871 +8871 execve("/usr/libexec/gcc/avr/ld", ["/usr/libexec/gcc/avr/ld", "-m", "avr5", "-Tdata", "0x800100", "-o", "battery_charger.elf", "/usr/lib/gcc/avr/4.3.3/../../../"..., "-L/usr/lib/gcc/avr/4.3.3/avr5", "-L/usr/lib/gcc/avr/4.3.3/../../."..., "-L/usr/lib/gcc/avr/4.3.3", "-L/usr/lib/gcc/avr/4.3.3/../../."..., "-u", "vfprintf", "-lprintf_min", "battery_charger.o", ...], [/* 59 vars */]) = 0 +8871 brk(0) = 0x9049000 +8871 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fd8000 +8871 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) +8871 open("/usr/i686-pc-linux-gnu/avr/lib/tls/i686/sse2/libbfd-2.19.1.so", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 stat64("/usr/i686-pc-linux-gnu/avr/lib/tls/i686/sse2", 0xbfdf4ffc) = -1 ENOENT (No such file or directory) +8871 open("/usr/i686-pc-linux-gnu/avr/lib/tls/i686/libbfd-2.19.1.so", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 stat64("/usr/i686-pc-linux-gnu/avr/lib/tls/i686", 0xbfdf4ffc) = -1 ENOENT (No such file or directory) +8871 open("/usr/i686-pc-linux-gnu/avr/lib/tls/sse2/libbfd-2.19.1.so", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 stat64("/usr/i686-pc-linux-gnu/avr/lib/tls/sse2", 0xbfdf4ffc) = -1 ENOENT (No such file or directory) +8871 open("/usr/i686-pc-linux-gnu/avr/lib/tls/libbfd-2.19.1.so", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 stat64("/usr/i686-pc-linux-gnu/avr/lib/tls", 0xbfdf4ffc) = -1 ENOENT (No such file or directory) +8871 open("/usr/i686-pc-linux-gnu/avr/lib/i686/sse2/libbfd-2.19.1.so", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 stat64("/usr/i686-pc-linux-gnu/avr/lib/i686/sse2", 0xbfdf4ffc) = -1 ENOENT (No such file or directory) +8871 open("/usr/i686-pc-linux-gnu/avr/lib/i686/libbfd-2.19.1.so", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 stat64("/usr/i686-pc-linux-gnu/avr/lib/i686", 0xbfdf4ffc) = -1 ENOENT (No such file or directory) +8871 open("/usr/i686-pc-linux-gnu/avr/lib/sse2/libbfd-2.19.1.so", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 stat64("/usr/i686-pc-linux-gnu/avr/lib/sse2", 0xbfdf4ffc) = -1 ENOENT (No such file or directory) +8871 open("/usr/i686-pc-linux-gnu/avr/lib/libbfd-2.19.1.so", O_RDONLY) = 3 +8871 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240#\1\0004\0\0\0\10"..., 512) = 512 +8871 fstat64(3, {st_mode=S_IFREG|0755, st_size=565784, ...}) = 0 +8871 mmap2(NULL, 581424, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7f4a000 +8871 mmap2(0xb7fcf000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x85) = 0xb7fcf000 +8871 mmap2(0xb7fd4000, 16176, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7fd4000 +8871 close(3) = 0 +8871 open("/usr/i686-pc-linux-gnu/avr/lib/libz.so.1", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 open("/etc/ld.so.cache", O_RDONLY) = 3 +8871 fstat64(3, {st_mode=S_IFREG|0644, st_size=105128, ...}) = 0 +8871 mmap2(NULL, 105128, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f30000 +8871 close(3) = 0 +8871 open("/lib/libz.so.1", O_RDONLY) = 3 +8871 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\27\0\0004\0\0\0\254"..., 512) = 512 +8871 fstat64(3, {st_mode=S_IFREG|0755, st_size=75156, ...}) = 0 +8871 mmap2(NULL, 78072, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7f1c000 +8871 mmap2(0xb7f2e000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x11) = 0xb7f2e000 +8871 close(3) = 0 +8871 open("/usr/i686-pc-linux-gnu/avr/lib/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 open("/lib/libc.so.6", O_RDONLY) = 3 +8871 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220g\1\0004\0\0\0\244"..., 512) = 512 +8871 fstat64(3, {st_mode=S_IFREG|0755, st_size=1302812, ...}) = 0 +8871 mmap2(NULL, 1308240, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7ddc000 +8871 mmap2(0xb7f16000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x13a) = 0xb7f16000 +8871 mmap2(0xb7f19000, 9808, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7f19000 +8871 close(3) = 0 +8871 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7ddb000 +8871 set_thread_area({entry_number:-1 -> 6, base_addr:0xb7ddb6c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 +8871 mprotect(0xb7f16000, 8192, PROT_READ) = 0 +8871 mprotect(0xb7f2e000, 4096, PROT_READ) = 0 +8871 mprotect(0xb7fcf000, 16384, PROT_READ) = 0 +8871 mprotect(0x809c000, 4096, PROT_READ) = 0 +8871 mprotect(0xb7ff5000, 4096, PROT_READ) = 0 +8871 munmap(0xb7f30000, 105128) = 0 +8871 getrusage(RUSAGE_SELF, {ru_utime={0, 0}, ru_stime={0, 2999}, ...}) = 0 +8871 brk(0) = 0x9049000 +8871 brk(0x906a000) = 0x906a000 +8871 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec/gcc", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec/gcc/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec/gcc/avr/ld", {st_mode=S_IFLNK|0777, st_size=49, ...}) = 0 +8871 readlink("/usr/libexec/gcc/avr/ld", "/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1/ld"..., 4096) = 49 +8871 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr/binutils-bin", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1/ld", {st_mode=S_IFREG|0755, st_size=349460, ...}) = 0 +8871 stat64("/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1/../../../../avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr/binutils-bin", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib", {st_mode=S_IFDIR|0755, st_size=69632, ...}) = 0 +8871 lstat64("/usr/lib/gcc", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib/gcc/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib/gcc/avr/4.3.3", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib/gcc/avr/4.3.3/avr5", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib", {st_mode=S_IFDIR|0755, st_size=69632, ...}) = 0 +8871 lstat64("/usr/lib/gcc", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib/gcc/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib/gcc/avr/4.3.3", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/avr/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/avr/lib/avr5", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib", {st_mode=S_IFDIR|0755, st_size=69632, ...}) = 0 +8871 lstat64("/usr/lib/gcc", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib/gcc/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib/gcc/avr/4.3.3", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib", {st_mode=S_IFDIR|0755, st_size=69632, ...}) = 0 +8871 lstat64("/usr/lib/gcc", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib/gcc/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/lib/gcc/avr/4.3.3", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/avr/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 open("ldscripts/avr5.x", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec/gcc", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec/gcc/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec/gcc/avr/ld", {st_mode=S_IFLNK|0777, st_size=49, ...}) = 0 +8871 readlink("/usr/libexec/gcc/avr/ld", "/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1/ld"..., 4096) = 49 +8871 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr/binutils-bin", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1/ld", {st_mode=S_IFREG|0755, st_size=349460, ...}) = 0 +8871 stat64("/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1/../../../../avr/lib/ldscripts", 0xbfdf5504) = -1 ENOENT (No such file or directory) +8871 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec/gcc", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec/gcc/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/libexec/gcc/avr/ld", {st_mode=S_IFLNK|0777, st_size=49, ...}) = 0 +8871 readlink("/usr/libexec/gcc/avr/ld", "/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1/ld"..., 4096) = 49 +8871 lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr/binutils-bin", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 +8871 lstat64("/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1/ld", {st_mode=S_IFREG|0755, st_size=349460, ...}) = 0 +8871 stat64("/usr/i686-pc-linux-gnu/avr/binutils-bin/2.19.1/../lib/ldscripts", 0xbfdf5504) = -1 ENOENT (No such file or directory) +8871 stat64("/usr/avr/lib/ldscripts", 0xbfdf5504) = -1 ENOENT (No such file or directory) +8871 stat64("/usr/libexec/gcc/avr/ldscripts", 0xbfdf5504) = -1 ENOENT (No such file or directory) +8871 stat64("/usr/libexec/gcc/avr/../lib/ldscripts", 0xbfdf5504) = -1 ENOENT (No such file or directory) +8871 open("/usr/lib/gcc/avr/4.3.3/avr5/ldscripts/avr5.x", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 open("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/ldscripts/avr5.x", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 open("/usr/lib/gcc/avr/4.3.3/ldscripts/avr5.x", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 open("/usr/lib/gcc/avr/4.3.3/../../../../avr/lib/ldscripts/avr5.x", O_RDONLY) = -1 ENOENT (No such file or directory) +8871 write(2, "/usr/libexec/gcc/avr/ld"..., 23) = 23 +8871 write(2, ":"..., 1) = 1 +8871 write(2, " "..., 1) = 1 +8871 write(2, "c"..., 1) = 1 +8871 write(2, "a"..., 1) = 1 +8871 write(2, "n"..., 1) = 1 +8871 write(2, "n"..., 1) = 1 +8871 write(2, "o"..., 1) = 1 +8871 write(2, "t"..., 1) = 1 +8871 write(2, " "..., 1) = 1 +8871 write(2, "o"..., 1) = 1 +8871 write(2, "p"..., 1) = 1 +8871 write(2, "e"..., 1) = 1 +8871 write(2, "n"..., 1) = 1 +8871 write(2, " "..., 1) = 1 +8871 write(2, "l"..., 1) = 1 +8871 write(2, "i"..., 1) = 1 +8871 write(2, "n"..., 1) = 1 +8871 write(2, "k"..., 1) = 1 +8871 write(2, "e"..., 1) = 1 +8871 write(2, "r"..., 1) = 1 +8871 write(2, " "..., 1) = 1 +8871 write(2, "s"..., 1) = 1 +8871 write(2, "c"..., 1) = 1 +8871 write(2, "r"..., 1) = 1 +8871 write(2, "i"..., 1) = 1 +8871 write(2, "p"..., 1) = 1 +8871 write(2, "t"..., 1) = 1 +8871 write(2, " "..., 1) = 1 +8871 write(2, "f"..., 1) = 1 +8871 write(2, "i"..., 1) = 1 +8871 write(2, "l"..., 1) = 1 +8871 write(2, "e"..., 1) = 1 +8871 write(2, " "..., 1) = 1 +8871 write(2, "ldscripts/avr5.x"..., 16) = 16 +8871 write(2, ":"..., 1) = 1 +8871 write(2, " "..., 1) = 1 +8871 write(2, "No such file or directory"..., 25) = 25 +8871 write(2, "\n"..., 1) = 1 +8871 exit_group(1) = ? +8870 --- SIGCHLD (Child exited) @ 0 (0) --- +8870 waitpid(8871, [{WIFEXITED(s) && WEXITSTATUS(s) == 1}], 0) = 8871 +8870 exit_group(1) = ? diff --git a/battery_charger/ringbuffer.c b/battery_charger/ringbuffer.c new file mode 100644 index 0000000..13c9f42 --- /dev/null +++ b/battery_charger/ringbuffer.c @@ -0,0 +1,89 @@ +#include "ringbuffer.h" + +uint16_t _rb_mod(uint16_t num, uint16_t denom) +{ + for (; num >= denom; num -= denom); + return num; +} + +void ringbuffer_init(ringbuffer *buf, int bufsize) +{ + buf->read_pointer = 0; + buf->write_pointer = 0; + buf->size = bufsize - sizeof(ringbuffer); +} + +uint16_t ringbuffer_canread(ringbuffer *buf) +{ + return _rb_mod(buf->write_pointer + buf->size + buf->size - buf->read_pointer, buf->size); +} + +uint16_t ringbuffer_canwrite(ringbuffer *buf) +{ + return _rb_mod(buf->read_pointer + buf->size + buf->size - buf->write_pointer - 1, buf->size); +} + +uint8_t ringbuffer_readchar(ringbuffer *buf) +{ + uint8_t r = 0; + if (ringbuffer_canread(buf)) + { + r = buf->data[buf->read_pointer]; + buf->read_pointer = _rb_mod(buf->read_pointer + 1, buf->size); + } + return r; +} + +void ringbuffer_writechar(ringbuffer *buf, uint8_t data) +{ + if (ringbuffer_canwrite(buf)) + { + buf->data[buf->write_pointer] = data; + buf->write_pointer = _rb_mod(buf->write_pointer + 1, buf->size); + } +} + + +uint8_t ringbuffer_peekchar(ringbuffer *buf, uint16_t index) +{ + return buf->data[_rb_mod(buf->read_pointer + index, buf->size)]; +} + +uint16_t ringbuffer_readblock(ringbuffer *buf, uint8_t *newbuf, int size) +{ + uint16_t nc, i; + uint8_t *rp, *ms; + if ((nc = ringbuffer_canread(buf)) < size) + size = nc; + if (size) + { + for (i = 0, rp = buf->data + buf->read_pointer, ms = buf->data + buf->size; i < size; i++, rp++) + { + if (rp >= ms) + rp = buf->data; + newbuf[i] = *rp; + } + buf->read_pointer = rp - buf->data; + } + return size; +} + +uint16_t ringbuffer_writeblock(ringbuffer *buf, uint8_t *data, int size) +{ + uint16_t nc, i; + uint8_t *wp, *ms; + + if ((nc = ringbuffer_canwrite(buf)) < size) + size = nc; + if (size) + { + for (i = 0, wp = buf->write_pointer + buf->data, ms = buf->data + buf->size; i < size; i++, wp++) + { + if (wp >= ms) + wp = buf->data; + *wp = data[i]; + } + buf->write_pointer = wp - buf->data; + } + return size; +} diff --git a/battery_charger/ringbuffer.h b/battery_charger/ringbuffer.h new file mode 100644 index 0000000..c6a24f4 --- /dev/null +++ b/battery_charger/ringbuffer.h @@ -0,0 +1,26 @@ +#ifndef _RINGBUFFER_H +#define _RINGBUFFER_H + +#include +#include + +typedef struct { + uint16_t read_pointer; + uint16_t write_pointer; + uint16_t size; + uint8_t data[]; +} ringbuffer; + +void ringbuffer_init(ringbuffer *buf, int bufsize); + +uint16_t ringbuffer_canread(ringbuffer *buf); +uint16_t ringbuffer_canwrite(ringbuffer *buf); + +uint8_t ringbuffer_readchar(ringbuffer *buf); +uint8_t ringbuffer_peekchar(ringbuffer *buf, uint16_t index); +uint16_t ringbuffer_readblock(ringbuffer *buf, uint8_t *newbuf, int size); + +void ringbuffer_writechar(ringbuffer *buf, uint8_t data); +uint16_t ringbuffer_writeblock(ringbuffer *buf, uint8_t *data, int size); + +#endif /* _RINGBUFFER_H */ diff --git a/battery_charger/serial.c b/battery_charger/serial.c new file mode 100644 index 0000000..3a691d6 --- /dev/null +++ b/battery_charger/serial.c @@ -0,0 +1,72 @@ +#include "serial.h" + +#include "ringbuffer.h" + +#define BUFSIZE 64 + sizeof(ringbuffer) +#define BAUD 19200 + +volatile uint8_t _rx_buffer[BUFSIZE]; +volatile uint8_t _tx_buffer[BUFSIZE]; + +void serial_init(uint16_t baud) +{ + ringbuffer_init(rx_buffer, BUFSIZE); + ringbuffer_init(tx_buffer, BUFSIZE); + + UCSR0A = 0; + UCSR0B = (1 << RXEN0) | (1 << TXEN0); + UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); + + UBRR0 = ((F_CPU / 16) / baud) - 1; + + UCSR0B |= (1 << RXCIE0) | (1 << UDRIE0); +} + +ISR(USART_RX_vect) +{ + ringbuffer_writechar(rx_buffer, UDR0); +} + +ISR(USART_UDRE_vect) +{ + if (ringbuffer_canread(tx_buffer)) + { + UDR0 = ringbuffer_readchar(tx_buffer); + } + else + { + UCSR0B &= ~(1 << UDRIE0); + } +} + +uint16_t serial_rxchars() +{ + return ringbuffer_canread(rx_buffer); +} + +uint16_t serial_txchars() +{ + return ringbuffer_canread(tx_buffer); +} + +uint8_t serial_popchar() +{ + return ringbuffer_readchar(rx_buffer); +} + +uint16_t serial_recvblock(uint8_t *block, int blocksize) +{ + return ringbuffer_readblock(rx_buffer, block, blocksize); +} + +void serial_writechar(uint8_t data) +{ + ringbuffer_writechar(tx_buffer, data); + UCSR0B |= (1 << UDRIE0); +} + +void serial_writeblock(uint8_t *data, int datalen) +{ + ringbuffer_writeblock(tx_buffer, data, datalen); + UCSR0B |= (1 << UDRIE0); +} diff --git a/battery_charger/serial.h b/battery_charger/serial.h new file mode 100644 index 0000000..efda9d6 --- /dev/null +++ b/battery_charger/serial.h @@ -0,0 +1,24 @@ +#ifndef _SERIAL_H +#define _SERIAL_H + +#include +#include + +#define rx_buffer ((ringbuffer *) _rx_buffer) +#define tx_buffer ((ringbuffer *) _tx_buffer) + +extern volatile uint8_t _rx_buffer[]; +extern volatile uint8_t _tx_buffer[]; + +void serial_init(uint16_t baud); + +uint16_t serial_rxchars(void); +uint16_t serial_txchars(void); + +uint8_t serial_popchar(void); +void serial_writechar(uint8_t data); + +uint16_t serial_recvblock(uint8_t *block, int blocksize); +void serial_writeblock(uint8_t *data, int datalen); + +#endif /* _SERIAL_H */ diff --git a/freq-counter/Makefile b/freq-counter/Makefile new file mode 100644 index 0000000..04b9b2f --- /dev/null +++ b/freq-counter/Makefile @@ -0,0 +1,52 @@ + + +MCU_TARGET = atmega168 +F_CPU = 16000000L + + +ARCH = avr- +OPTIMIZE = -Os +CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(F_CPU) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +LDFLAGS = -Wl,-u,vfprintf -lprintf_min + +CC = $(ARCH)gcc +OBJDUMP = $(ARCH)objdump +OBJCOPY = $(ARCH)objcopy +AVRDUDE = ~/bin/avrdude + +PROGPORT = /dev/arduino +PROGBAUD = 19200 + +PROGRAM = freq-counter + +SOURCES = $(PROGRAM).c ringbuffer.c serial.c lcd.c + +OBJ = $(patsubst %.c,%.o,${SOURCES}) + +.PHONY: all program clean +.PRECIOUS: %.o %.elf + +all: $(PROGRAM).hex $(PROGRAM).lst + +program: $(PROGRAM).hex + stty $(PROGBAUD) raw ignbrk hup < $(PROGPORT) + $(AVRDUDE) -cstk500v1 -b$(PROGBAUD) -p$(MCU_TARGET) -P$(PROGPORT) -C/etc/avrdude.conf -U flash:w:$^ + stty -hup -echo < $(PROGPORT) + +clean: + rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al + +%.o: %.c + $(CC) -c $(CFLAGS) -Wa,-adhlns=$(<:.c=.al) -o $@ $^ + +%.elf: $(OBJ) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + +%.lst: %.elf + $(OBJDUMP) -h -S $< > $@ + +%.hex: %.elf + $(OBJCOPY) -j .text -j .data -O ihex $< $@ + +%.bin: %.elf + $(OBJCOPY) -j .text -j .data -O binary $< $@ diff --git a/freq-counter/freq-counter.c b/freq-counter/freq-counter.c new file mode 100644 index 0000000..5bd96b9 --- /dev/null +++ b/freq-counter/freq-counter.c @@ -0,0 +1,109 @@ +#include +#include +#include + +#include +#include + +#include "ringbuffer.h" +#include "serial.h" +#include "lcd.h" + +volatile uint16_t last_count; +volatile uint32_t freq; +volatile uint8_t jiffies; + +char *teststring = "chickens\n"; + +// write to lcd function for fdev_setup_stream +static int lcd_putc_fdev(char c, FILE *stream) +{ + lcd_putc(c); + return 0; +} + +int serial_putc_fdev(char c, FILE *stream) +{ + serial_writechar((uint8_t) c); + return 0; +} + +int serial_getc_fdev(FILE *stream) +{ + for (;serial_rxchars() == 0;); + return (int) serial_popchar(); +} + +static FILE lcdo = FDEV_SETUP_STREAM(lcd_putc_fdev, NULL, _FDEV_SETUP_WRITE); +static FILE serio = FDEV_SETUP_STREAM(serial_putc_fdev, serial_getc_fdev, _FDEV_SETUP_RW); + +int main (void) +{ + // set up LCD + lcd_init(LCD_DISP_ON_CURSOR); + + lcd_puts_P("Starting..."); + + // set up outputs + PORTB &= ~(1 << PB5); + DDRB |= (1 << PB5); + + // set up STDIN/OUT/ERR + stdin = &serio; + stdout = &lcdo; + stderr = &lcdo; + + // set up timer 0 + // prescale 1024 = 15625khz + // so set clear on compare mode and set OCRA to 156 for a ~100Hz (actually 100.160256Hz) rate + // use interrupt to write value into a ringbuffer + OCR0A = F_CPU / 1024 / 100; + TCCR0A = (1 << WGM01) | (0 << WGM00); + TCCR0B = (1 << CS02) | (0 << CS01) | (1 << CS00); + TIMSK0 = (1 << OCIE0A); + + // set up timer 1 + // no prescale, use external input for counter, no compare, no interrupts + TCCR1A = 0; + TCCR1B = (0 << ICNC1) | (0 << ICES1) | (0 << WGM13) | (0 << WGM12) | (1 << CS12) | (1 << CS11) | (0 << CS10); + TCCR1C = 0; + + // set up globals + last_count = 0; + jiffies = 0; + + // set up serial + serial_init(19200); + + // set up pull-up on T1 (PD5) + PORTD |= (1 << PD5); + + sei(); + + lcd_gotoxy(0, 0); + fprintf(&lcdo, "Freq. Counter OK"); + + for (;;) + { + if (jiffies >= 50) + { + lcd_gotoxy(0, 1); + fprintf(&lcdo, "F: %liHz", freq << 1); + if (serial_txchars() == 0) + { + fprintf(&serio, "%liHz\n", freq << 1); + } + PORTB ^= (1 << PB5); + jiffies = 0; + freq = 0; + } + } +} + +ISR(TIMER0_COMPA_vect) +{ + last_count = TCNT1; + TCNT1 = 0; + freq += last_count; + jiffies++; +} diff --git a/freq-counter/lcd.c b/freq-counter/lcd.c new file mode 100644 index 0000000..1505eff --- /dev/null +++ b/freq-counter/lcd.c @@ -0,0 +1,595 @@ +/**************************************************************************** + Title : HD44780U LCD library + Author: Peter Fleury http://jump.to/fleury + File: $Id: lcd.c,v 1.14.2.1 2006/01/29 12:16:41 peter Exp $ + Software: AVR-GCC 3.3 + Target: any AVR device, memory mapped mode only for AT90S4414/8515/Mega + + DESCRIPTION + Basic routines for interfacing a HD44780U-based text lcd display + + Originally based on Volker Oth's lcd library, + changed lcd_init(), added additional constants for lcd_command(), + added 4-bit I/O mode, improved and optimized code. + + Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in + 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported. + + Memory mapped mode compatible with Kanda STK200, but supports also + generation of R/W signal through A8 address line. + + USAGE + See the C include lcd.h file for a description of each function + +*****************************************************************************/ +#include +#include +#include +#include "lcd.h" + + + +/* +** constants/macros +*/ +#define DDR(x) (*(&x - 1)) /* address of data direction register of port x */ +#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) + /* on ATmega64/128 PINF is on port 0x00 and not 0x60 */ + #define PIN(x) ( &PORTF==&(x) ? _SFR_IO8(0x00) : (*(&x - 2)) ) +#else + #define PIN(x) (*(&x - 2)) /* address of input register of port x */ +#endif + + +#if LCD_IO_MODE + #define lcd_e_delay() __asm__ __volatile__( "rjmp 1f\n 1:" ); + #define lcd_e_high() LCD_E_PORT |= _BV(LCD_E_PIN); + #define lcd_e_low() LCD_E_PORT &= ~_BV(LCD_E_PIN); + #define lcd_e_toggle() toggle_e() + #define lcd_rw_high() LCD_RW_PORT |= _BV(LCD_RW_PIN) + #define lcd_rw_low() LCD_RW_PORT &= ~_BV(LCD_RW_PIN) + #define lcd_rs_high() LCD_RS_PORT |= _BV(LCD_RS_PIN) + #define lcd_rs_low() LCD_RS_PORT &= ~_BV(LCD_RS_PIN) +#endif + +#if LCD_IO_MODE + #if LCD_LINES==1 + #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE + #else + #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES + #endif +#else + #if LCD_LINES==1 + #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_1LINE + #else + #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_2LINES + #endif +#endif + +#if LCD_CONTROLLER_KS0073 + #if LCD_LINES==4 + #define KS0073_EXTENDED_FUNCTION_REGISTER_ON 0x24 /* |0|010|0100 4-bit mode extension-bit RE = 1 */ + #define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x20 /* |0|000|1001 4 lines mode */ + #define KS0073_4LINES_MODE 0x09 /* |0|001|0000 4-bit mode, extension-bit RE = 0 */ + #endif +#endif + +/* +** function prototypes +*/ +#if LCD_IO_MODE +static void toggle_e(void); +#endif + +/* +** local functions +*/ + + + +/************************************************************************* + delay loop for small accurate delays: 16-bit counter, 4 cycles/loop +*************************************************************************/ +static inline void _delayFourCycles(unsigned int __count) +{ + if ( __count == 0 ) + __asm__ __volatile__( "rjmp 1f\n 1:" ); // 2 cycles + else + __asm__ __volatile__ ( + "1: sbiw %0,1" "\n\t" + "brne 1b" // 4 cycles/loop + : "=w" (__count) + : "0" (__count) + ); +} + + +/************************************************************************* +delay for a minimum of microseconds +the number of loops is calculated at compile-time from MCU clock frequency +*************************************************************************/ +#define delay(us) _delayFourCycles( ( ( 1*(XTAL/4000) )*us)/1000 ) + + +#if LCD_IO_MODE +/* toggle Enable Pin to initiate write */ +static void toggle_e(void) +{ + lcd_e_high(); + lcd_e_delay(); + lcd_e_low(); +} +#endif + + +/************************************************************************* +Low-level function to write byte to LCD controller +Input: data byte to write to LCD + rs 1: write data + 0: write instruction +Returns: none +*************************************************************************/ +#if LCD_IO_MODE +static void lcd_write(uint8_t data,uint8_t rs) +{ + if (rs) { /* write data (RS=1, RW=0) */ + lcd_rs_high(); + } else { /* write instruction (RS=0, RW=0) */ + lcd_rs_low(); + } + lcd_rw_low(); + + if ( + (&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) + && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) + ) + { + /* configure data pins as output */ + DDR(LCD_DATA0_PORT) |= 0x0F; + + /* output high nibble first */ + LCD_DATA0_PORT = (LCD_DATA0_PORT & 0xF0) | ((data >> 4) & 0x0F); + lcd_e_toggle(); + + /* output low nibble */ + LCD_DATA0_PORT = (LCD_DATA0_PORT & 0xF0) | (data & 0x0F); + lcd_e_toggle(); + + /* all data pins high (inactive) */ + LCD_DATA0_PORT = (LCD_DATA0_PORT & 0xF0) | 0x0F; + } + else + { + /* configure data pins as output */ + DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); + DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); + DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); + DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); + + /* output high nibble first */ + LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); + LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); + LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); + if(data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + if(data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + if(data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + if(data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + lcd_e_toggle(); + + /* output low nibble */ + LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); + LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); + LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); + if(data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + if(data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + if(data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + if(data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + lcd_e_toggle(); + + /* all data pins high (inactive) */ + LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + } +} +#else +#define lcd_write(d,rs) if (rs) *(volatile uint8_t*)(LCD_IO_DATA) = d; else *(volatile uint8_t*)(LCD_IO_FUNCTION) = d; +/* rs==0 -> write instruction to LCD_IO_FUNCTION */ +/* rs==1 -> write data to LCD_IO_DATA */ +#endif + + +/************************************************************************* +Low-level function to read byte from LCD controller +Input: rs 1: read data + 0: read busy flag / address counter +Returns: byte read from LCD controller +*************************************************************************/ +#if LCD_IO_MODE +static uint8_t lcd_read(uint8_t rs) +{ + uint8_t data; + + if (rs) + lcd_rs_high(); /* RS=1: read data */ + else + lcd_rs_low(); /* RS=0: read busy flag */ + lcd_rw_high(); /* RW=1 read mode */ + + if ( + (&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) + && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) + ) + { + DDR(LCD_DATA0_PORT) &= 0xF0; /* configure data pins as input */ + + lcd_e_high(); + lcd_e_delay(); + data = PIN(LCD_DATA0_PORT) << 4; /* read high nibble first */ + lcd_e_low(); + + lcd_e_delay(); /* Enable 500ns low */ + + lcd_e_high(); + lcd_e_delay(); + data |= PIN(LCD_DATA0_PORT) & 0x0F; /* read low nibble */ + lcd_e_low(); + } + else + { + /* configure data pins as input */ + DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN); + DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN); + DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN); + DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN); + + /* read high nibble first */ + lcd_e_high(); + lcd_e_delay(); + data = 0; + if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x10; + if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x20; + if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x40; + if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x80; + lcd_e_low(); + + lcd_e_delay(); /* Enable 500ns low */ + + /* read low nibble */ + lcd_e_high(); + lcd_e_delay(); + if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x01; + if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x02; + if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x04; + if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x08; + lcd_e_low(); + } + return data; +} +#else +#define lcd_read(rs) (rs) ? *(volatile uint8_t*)(LCD_IO_DATA+LCD_IO_READ) : *(volatile uint8_t*)(LCD_IO_FUNCTION+LCD_IO_READ) +/* rs==0 -> read instruction from LCD_IO_FUNCTION */ +/* rs==1 -> read data from LCD_IO_DATA */ +#endif + + +/************************************************************************* +loops while lcd is busy, returns address counter +*************************************************************************/ +static uint8_t lcd_waitbusy(void) +{ + /* wait until busy flag is cleared */ + for (; lcd_read(0) & (1 << LCD_BUSY); ); + + /* the address counter is updated 4us after the busy flag is cleared */ + delay(2); + + /* now read the address counter */ + return (lcd_read(0)); // return address counter +}/* lcd_waitbusy */ + + +/************************************************************************* +Move cursor to the start of next line or to the first line if the cursor +is already on the last line. +*************************************************************************/ +static inline void lcd_newline(uint8_t pos) +{ + register uint8_t addressCounter; + +#if LCD_LINES==1 + addressCounter = 0; +#endif +#if LCD_LINES==2 + if ( pos < (LCD_START_LINE2) ) + addressCounter = LCD_START_LINE2; + else + addressCounter = LCD_START_LINE1; +#endif +#if LCD_LINES==4 +#if KS0073_4LINES_MODE + if ( pos < LCD_START_LINE2 ) + addressCounter = LCD_START_LINE2; + else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3) ) + addressCounter = LCD_START_LINE3; + else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4) ) + addressCounter = LCD_START_LINE4; + else + addressCounter = LCD_START_LINE1; +#else + if ( pos < LCD_START_LINE3 ) + addressCounter = LCD_START_LINE2; + else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4) ) + addressCounter = LCD_START_LINE3; + else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) ) + addressCounter = LCD_START_LINE4; + else + addressCounter = LCD_START_LINE1; +#endif +#endif + lcd_command((1 << LCD_DDRAM) + addressCounter); + +}/* lcd_newline */ + + +/* +** PUBLIC FUNCTIONS +*/ + +/************************************************************************* +Send LCD controller instruction command +Input: instruction to send to LCD controller, see HD44780 data sheet +Returns: none +*************************************************************************/ +void lcd_command(uint8_t cmd) +{ + lcd_waitbusy(); + lcd_write(cmd,0); +} + + +/************************************************************************* +Send data byte to LCD controller +Input: data to send to LCD controller, see HD44780 data sheet +Returns: none +*************************************************************************/ +void lcd_data(uint8_t data) +{ + lcd_waitbusy(); + lcd_write(data,1); +} + + + +/************************************************************************* +Set cursor to specified position +Input: x horizontal position (0: left most position) + y vertical position (0: first line) +Returns: none +*************************************************************************/ +void lcd_gotoxy(uint8_t x, uint8_t y) +{ +#if LCD_LINES==1 + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); +#endif +#if LCD_LINES==2 + if ( y==0 ) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); + else + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x); +#endif +#if LCD_LINES==4 + if ( y==0 ) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); + else if ( y==1) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x); + else if ( y==2) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE3 + x); + else /* y==3 */ + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE4 + x); +#endif + +}/* lcd_gotoxy */ + + +/************************************************************************* +*************************************************************************/ +int lcd_getxy(void) +{ + return lcd_waitbusy(); +} + + +/************************************************************************* +Clear display and set cursor to home position +*************************************************************************/ +void lcd_clrscr(void) +{ + lcd_command(1 << LCD_CLR); +} + + +/************************************************************************* +Set cursor to home position +*************************************************************************/ +void lcd_home(void) +{ + lcd_command(1 << LCD_HOME); +} + + +/************************************************************************* +Display character at current cursor position +Input: character to be displayed +Returns: none +*************************************************************************/ +void lcd_putc(char c) +{ + uint8_t pos; + + pos = lcd_waitbusy(); // read busy-flag and address counter + if (c=='\n') + lcd_newline(pos); + else + { +#if LCD_WRAP_LINES==1 +#if LCD_LINES==1 + if ( pos == LCD_START_LINE1 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1,0); +#elif LCD_LINES==2 + if ( pos == LCD_START_LINE1 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2,0); + else if ( pos == LCD_START_LINE2 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1,0); +#elif LCD_LINES==4 + if ( pos == LCD_START_LINE1 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2,0); + else if ( pos == LCD_START_LINE2 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE3,0); + else if ( pos == LCD_START_LINE3 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE4,0); + else if ( pos == LCD_START_LINE4 + LCD_DISP_LENGTH ) + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1,0); +#endif + lcd_waitbusy(); +#endif + lcd_write(c, 1); + } + +}/* lcd_putc */ + + +/************************************************************************* +Display string without auto linefeed +Input: string to be displayed +Returns: none +*************************************************************************/ +void lcd_puts(const char *s) +/* print string on lcd (no auto linefeed) */ +{ + register char c; + + while ( (c = *s++) ) { + lcd_putc(c); + } + +}/* lcd_puts */ + + +/************************************************************************* +Display string from program memory without auto linefeed +Input: string from program memory be be displayed +Returns: none +*************************************************************************/ +void lcd_puts_p(const char *progmem_s) +/* print string from program memory on lcd (no auto linefeed) */ +{ + register char c; + + while ( (c = pgm_read_byte(progmem_s++)) ) { + lcd_putc(c); + } + +}/* lcd_puts_p */ + + +/************************************************************************* +Initialize display and select type of cursor +Input: dispAttr LCD_DISP_OFF display off + LCD_DISP_ON display on, cursor off + LCD_DISP_ON_CURSOR display on, cursor on + LCD_DISP_CURSOR_BLINK display on, cursor on flashing +Returns: none +*************************************************************************/ +void lcd_init(uint8_t dispAttr) +{ +#if LCD_IO_MODE + /* + * Initialize LCD to 4 bit I/O mode + */ + + if ( + ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT ) + && ( &LCD_RS_PORT == &LCD_DATA0_PORT) && ( &LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT) + ) + { + /* configure all port bits as output (all LCD lines on same port) */ + DDR(LCD_DATA0_PORT) |= (1 << LCD_DATA0_PIN) | (1 << LCD_DATA1_PIN) | (1 << LCD_DATA2_PIN) | (1 << LCD_DATA3_PIN) | (1 << LCD_RS_PIN) | (1 << LCD_RW_PIN) | (1 << LCD_E_PIN); + } + else if ( + ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT ) + ) + { + /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */ + DDR(LCD_DATA0_PORT) |= (1 << LCD_DATA0_PIN) | (1 << LCD_DATA1_PIN) | (1 << LCD_DATA2_PIN) | (1 << LCD_DATA3_PIN); + DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); + DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); + DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); + } + else + { + /* configure all port bits as output (LCD data and control lines on different ports */ + DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); + DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); + DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); + DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); + DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); + DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); + DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); + } + delay(16000); /* wait 16ms or more after power-on */ + + /* initial write to lcd is 8bit */ + LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); // _BV(LCD_FUNCTION)>>4; + LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // _BV(LCD_FUNCTION_8BIT)>>4; + lcd_e_toggle(); + delay(4992); /* delay, busy flag can't be checked here */ + + /* repeat last command */ + lcd_e_toggle(); delay(64); /* delay, busy flag can't be checked here */ + + /* repeat last command a third time */ + lcd_e_toggle(); delay(64); /* delay, busy flag can't be checked here */ + + /* now configure for 4bit mode */ + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // LCD_FUNCTION_4BIT_1LINE>>4 + lcd_e_toggle(); + delay(64); /* some displays need this additional delay */ + + /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */ +#else + /* + * Initialize LCD to 8 bit memory mapped mode + */ + + /* enable external SRAM (memory mapped lcd) and one wait state */ + MCUCR = _BV(SRE) | _BV(SRW); + + /* reset LCD */ + delay(16000); /* wait 16ms after power-on */ + lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ + delay(4992); /* wait 5ms */ + lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ + delay(64); /* wait 64us */ + lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ + delay(64); /* wait 64us */ +#endif + +#if KS0073_4LINES_MODE + /* Display with KS0073 controller requires special commands for enabling 4 line mode */ + lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON); + lcd_command(KS0073_4LINES_MODE); + lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF); +#else + lcd_command(LCD_FUNCTION_DEFAULT); /* function set: display lines */ +#endif + + lcd_command(LCD_DISP_OFF); /* display off */ + lcd_clrscr(); /* display clear */ + lcd_command(LCD_MODE_DEFAULT); /* set entry mode */ + lcd_command(dispAttr); /* display/cursor control */ + +}/* lcd_init */ diff --git a/freq-counter/lcd.h b/freq-counter/lcd.h new file mode 100644 index 0000000..bec1cee --- /dev/null +++ b/freq-counter/lcd.h @@ -0,0 +1,263 @@ +#ifndef LCD_H +#define LCD_H +/************************************************************************* + Title : C include file for the HD44780U LCD library (lcd.c) + Author: Peter Fleury http://jump.to/fleury + File: $Id: lcd.h,v 1.13.2.2 2006/01/30 19:51:33 peter Exp $ + Software: AVR-GCC 3.3 + Hardware: any AVR device, memory mapped mode only for AT90S4414/8515/Mega +***************************************************************************/ + +/** + @defgroup pfleury_lcd LCD library + @code #include @endcode + + @brief Basic routines for interfacing a HD44780U-based text LCD display + + Originally based on Volker Oth's LCD library, + changed lcd_init(), added additional constants for lcd_command(), + added 4-bit I/O mode, improved and optimized code. + + Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in + 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported. + + Memory mapped mode compatible with Kanda STK200, but supports also + generation of R/W signal through A8 address line. + + @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury + + @see The chapter Interfacing a HD44780 Based LCD to an AVR + on my home page. + +*/ + +/*@{*/ + +#if (__GNUC__ * 100 + __GNUC_MINOR__) < 303 +#error "This library requires AVR-GCC 3.3 or later, update to newer AVR-GCC compiler !" +#endif + +#include +#include + +/** + * @name Definitions for MCU Clock Frequency + * Adapt the MCU clock frequency in Hz to your target. + */ +#define XTAL F_CPU /**< clock frequency in Hz, used to calculate delay timer */ + +/** + * @name Definition for LCD controller type + * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller. + */ +#define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */ + +/** + * @name Definitions for Display Size + * Change these definitions to adapt setting to your display + */ +#define LCD_LINES 2 /**< number of visible lines of the display */ +#define LCD_DISP_LENGTH 16 /**< visibles characters per line of the display */ +#define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */ +#define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ +#define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ +#define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ +#define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ +#define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */ + +#define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */ + +#if LCD_IO_MODE +/** + * @name Definitions for 4-bit IO mode + * Change LCD_PORT if you want to use a different port for the LCD pins. + * + * The four LCD data lines and the three control lines RS, RW, E can be on the + * same port or on different ports. + * Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on + * different ports. + * + * Normally the four data lines should be mapped to bit 0..3 on one port, but it + * is possible to connect these data lines in different order or even on different + * ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions. + * */ +#define LCD_PORT PORTB /**< port for the LCD lines */ +#define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */ +#define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */ +#define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ +#define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ +#define LCD_DATA0_PIN 0 /**< pin for 4bit data bit 0 */ +#define LCD_DATA1_PIN 1 /**< pin for 4bit data bit 1 */ +#define LCD_DATA2_PIN 2 /**< pin for 4bit data bit 2 */ +#define LCD_DATA3_PIN 3 /**< pin for 4bit data bit 3 */ +#define LCD_RS_PORT PORTD /**< port for RS line */ +#define LCD_RS_PIN 2 /**< pin for RS line */ +#define LCD_RW_PORT PORTD /**< port for RW line */ +#define LCD_RW_PIN 3 /**< pin for RW line */ +#define LCD_E_PORT PORTD /**< port for Enable line */ +#define LCD_E_PIN 4 /**< pin for Enable line */ + +#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || \ + defined(__AVR_ATmega8515__)|| defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || \ + defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__) +/* + * memory mapped mode is only supported when the device has an external data memory interface + */ +#define LCD_IO_DATA 0xC000 /* A15=E=1, A14=RS=1 */ +#define LCD_IO_FUNCTION 0x8000 /* A15=E=1, A14=RS=0 */ +#define LCD_IO_READ 0x0100 /* A8 =R/W=1 (R/W: 1=Read, 0=Write */ +#else +#error "external data memory interface not available for this device, use 4-bit IO port mode" + +#endif + + +/** + * @name Definitions for LCD command instructions + * The constants define the various LCD controller instructions which can be passed to the + * function lcd_command(), see HD44780 data sheet for a complete description. + */ + +/* instruction register bit positions, see HD44780U data sheet */ +#define LCD_CLR 0 /* DB0: clear display */ +#define LCD_HOME 1 /* DB1: return to home position */ +#define LCD_ENTRY_MODE 2 /* DB2: set entry mode */ +#define LCD_ENTRY_INC 1 /* DB1: 1=increment, 0=decrement */ +#define LCD_ENTRY_SHIFT 0 /* DB2: 1=display shift on */ +#define LCD_ON 3 /* DB3: turn lcd/cursor on */ +#define LCD_ON_DISPLAY 2 /* DB2: turn display on */ +#define LCD_ON_CURSOR 1 /* DB1: turn cursor on */ +#define LCD_ON_BLINK 0 /* DB0: blinking cursor ? */ +#define LCD_MOVE 4 /* DB4: move cursor/display */ +#define LCD_MOVE_DISP 3 /* DB3: move display (0-> cursor) ? */ +#define LCD_MOVE_RIGHT 2 /* DB2: move right (0-> left) ? */ +#define LCD_FUNCTION 5 /* DB5: function set */ +#define LCD_FUNCTION_8BIT 4 /* DB4: set 8BIT mode (0->4BIT mode) */ +#define LCD_FUNCTION_2LINES 3 /* DB3: two lines (0->one line) */ +#define LCD_FUNCTION_10DOTS 2 /* DB2: 5x10 font (0->5x7 font) */ +#define LCD_CGRAM 6 /* DB6: set CG RAM address */ +#define LCD_DDRAM 7 /* DB7: set DD RAM address */ +#define LCD_BUSY 7 /* DB7: LCD is busy */ + +/* set entry mode: display shift on/off, dec/inc cursor move direction */ +#define LCD_ENTRY_DEC 0x04 /* display shift off, dec cursor move dir */ +#define LCD_ENTRY_DEC_SHIFT 0x05 /* display shift on, dec cursor move dir */ +#define LCD_ENTRY_INC_ 0x06 /* display shift off, inc cursor move dir */ +#define LCD_ENTRY_INC_SHIFT 0x07 /* display shift on, inc cursor move dir */ + +/* display on/off, cursor on/off, blinking char at cursor position */ +#define LCD_DISP_OFF 0x08 /* display off */ +#define LCD_DISP_ON 0x0C /* display on, cursor off */ +#define LCD_DISP_ON_BLINK 0x0D /* display on, cursor off, blink char */ +#define LCD_DISP_ON_CURSOR 0x0E /* display on, cursor on */ +#define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char */ + +/* move cursor/shift display */ +#define LCD_MOVE_CURSOR_LEFT 0x10 /* move cursor left (decrement) */ +#define LCD_MOVE_CURSOR_RIGHT 0x14 /* move cursor right (increment) */ +#define LCD_MOVE_DISP_LEFT 0x18 /* shift display left */ +#define LCD_MOVE_DISP_RIGHT 0x1C /* shift display right */ + +/* function set: set interface data length and number of display lines */ +#define LCD_FUNCTION_4BIT_1LINE 0x20 /* 4-bit interface, single line, 5x7 dots */ +#define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line, 5x7 dots */ +#define LCD_FUNCTION_8BIT_1LINE 0x30 /* 8-bit interface, single line, 5x7 dots */ +#define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line, 5x7 dots */ + + +#define LCD_MODE_DEFAULT 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 Y%xJ#Bczjm?0M_H4fC2y%>HKx}Uv~4(`~Uy| literal 0 HcmV?d00001 diff --git a/freq-counter/lcdlibrary/doxygen.css b/freq-counter/lcdlibrary/doxygen.css new file mode 100644 index 0000000..8cb8b2e --- /dev/null +++ b/freq-counter/lcdlibrary/doxygen.css @@ -0,0 +1,49 @@ +H1 { text-align: center; } +CAPTION { font-weight: bold } +A.qindex {} +A.qindexRef {} +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code { text-decoration: none; font-weight: normal; color: #4444ee } +A.codeRef { font-weight: normal; color: #4444ee } +A:hover { text-decoration: none; background-color: #f2f2ff } +DL.el { margin-left: -1cm } +DIV.fragment { width: 100%; border: none; background-color: #eeeeee } +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #f2f2ff; font-weight: bold; } +TD.mdname1 { background-color: #f2f2ff; font-weight: bold; color: #602020; } +TD.mdname { background-color: #f2f2ff; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold } +DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller } +BODY { background: white; color: black } +TD.indexkey { + background-color: #eeeeff; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} +TD.indexvalue { + background-color: #eeeeff; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} +span.keyword { color: #008000 } +span.keywordtype { color: #604020 } +span.keywordflow { color: #e08000 } +span.comment { color: #800000 } +span.preprocessor { color: #806020 } +span.stringliteral { color: #002080 } +span.charliteral { color: #008080 } diff --git a/freq-counter/lcdlibrary/doxygen.png b/freq-counter/lcdlibrary/doxygen.png new file mode 100644 index 0000000000000000000000000000000000000000..f0a274bbaffdd67f6d784c894d9cf28729db0e14 GIT binary patch literal 1281 zcmaJ>ZA?>F7(Vx-ms?uoS`b@hdRtpo6o^%HU>M$hfGrBvQnk$LE?p^P!kn&ikhyq! zX~V@&tPF5Qt@V?oTL96Bi%aRiwbe1)9DWQI#?)=HxS7QSw`J`5fAJ*eJbB;uNuKA& zdERDo*{Y<(If(#(B$Lr#;nB(8Y#ia=ZCeW?JfPLuQY`=@cW$k}Rivq|vbxGrRq1Tl9;+(gNt?}UtVKM2`T5t1jLzuL@0UIs`S#vlhl4)^ zLgSYrPj@$+`|j?eSbXTmiHGkWxV8V}BzNR?pl9k_s4pDu9vd5a_UzZEPk)}Ad{AV_ zzddrjrh4=Imr`E06;LY{)YYt?o}L~H@7C}F^WB!Ra=v`Q0bj{>5&$66CWF>mf6vjP z2N>RRY6ZYa=K`76>+|_)Xdwko+7wv}7cN|btOhWb(*{sta~6b?S8Omrxw}!4`NhGr zZVpNqpu1@BE`QGWNTpEpcJVW5izu~2B^GlM?1(OPg)zwW;QcP@Ltcclm>XbJL9C|j z=9!2?ua=uIlf0%AndzHsRC}IyTL$EhAee(fdKB`?27KeS^2M8M_7b~PiCFO&r5LC7 z7gl1*a<8;SjNaw#h=843_AV9iZbWQOAp5YOC^&_F*9K0> zB|6%IDb?aM#3viTxkLU4aXg&@+CkNTOnQ1iMP*^?b|^lJy$4C)Zk4isV!|RZ*XhXh zw8q3$=*0LeGC!XI_Wc?dkT~3+*Gu%%yIqP+Wr3H$=&ROMQU6q}Ag^P~>c5vAEO;a- z_dK-3PPeKar%)6$j~vI2#*-YH!1h6HYVtwCX5_wM`iF#UKz&&@9Oo5w3%XGYrX zW>dY~)SG-((Yim%`InwgTvyRC?e=Wh^8KCao!R6Eg&TpVWUY1sN~4G}V?nFnEGo-; zHZ_$eW9-GnC%^WS9b z@p;-$oH#MtC0v>Q$HX%4^JdFdO$0cbv-W)Q TtK}Eh@>>I#ipmV1>S*>q-hkC} literal 0 HcmV?d00001 diff --git a/freq-counter/lcdlibrary/group__pfleury__lcd.html b/freq-counter/lcdlibrary/group__pfleury__lcd.html new file mode 100644 index 0000000..ddfffb0 --- /dev/null +++ b/freq-counter/lcdlibrary/group__pfleury__lcd.html @@ -0,0 +1,1174 @@ + + +AVR-GCC libraries: LCD library + + + + +

LCD library


Detailed Description

+Basic routines for interfacing a HD44780U-based text LCD display. +

+

 #include <lcd.h> 
+

+Originally based on Volker Oth's LCD library, changed lcd_init(), added additional constants for lcd_command(), added 4-bit I/O mode, improved and optimized code.

+Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported.

+Memory mapped mode compatible with Kanda STK200, but supports also generation of R/W signal through A8 address line.

+

Author:
Peter Fleury pfleury@gmx.ch http://jump.to/fleury
+
See also:
The chapter Interfacing a HD44780 Based LCD to an AVR on my home page.
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Definitions for MCU Clock Frequency

Adapt the MCU clock frequency in Hz to your target.

#define XTAL   4000000

Definition for LCD controller type

Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller.

#define LCD_CONTROLLER_KS0073   0

Definitions for Display Size

Change these definitions to adapt setting to your display

#define LCD_LINES   2
#define LCD_DISP_LENGTH   16
#define LCD_LINE_LENGTH   0x40
#define LCD_START_LINE1   0x00
#define LCD_START_LINE2   0x40
#define LCD_START_LINE3   0x14
#define LCD_START_LINE4   0x54
#define LCD_WRAP_LINES   0
#define LCD_IO_MODE   1

Definitions for 4-bit IO mode

Change LCD_PORT if you want to use a different port for the LCD pins.

+The four LCD data lines and the three control lines RS, RW, E can be on the same port or on different ports. Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on different ports.

+Normally the four data lines should be mapped to bit 0..3 on one port, but it is possible to connect these data lines in different order or even on different ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions.

#define LCD_PORT   PORTA
#define LCD_DATA0_PORT   LCD_PORT
#define LCD_DATA1_PORT   LCD_PORT
#define LCD_DATA2_PORT   LCD_PORT
#define LCD_DATA3_PORT   LCD_PORT
#define LCD_DATA0_PIN   0
#define LCD_DATA1_PIN   1
#define LCD_DATA2_PIN   2
#define LCD_DATA3_PIN   3
#define LCD_RS_PORT   LCD_PORT
#define LCD_RS_PIN   4
#define LCD_RW_PORT   LCD_PORT
#define LCD_RW_PIN   5
#define LCD_E_PORT   LCD_PORT
#define LCD_E_PIN   6

Definitions for LCD command instructions

The constants define the various LCD controller instructions which can be passed to the function lcd_command(), see HD44780 data sheet for a complete description.

+#define LCD_CLR   0
+#define LCD_HOME   1
+#define LCD_ENTRY_MODE   2
+#define LCD_ENTRY_INC   1
+#define LCD_ENTRY_SHIFT   0
+#define LCD_ON   3
+#define LCD_ON_DISPLAY   2
+#define LCD_ON_CURSOR   1
+#define LCD_ON_BLINK   0
+#define LCD_MOVE   4
+#define LCD_MOVE_DISP   3
+#define LCD_MOVE_RIGHT   2
+#define LCD_FUNCTION   5
+#define LCD_FUNCTION_8BIT   4
+#define LCD_FUNCTION_2LINES   3
+#define LCD_FUNCTION_10DOTS   2
+#define LCD_CGRAM   6
+#define LCD_DDRAM   7
+#define LCD_BUSY   7
+#define LCD_ENTRY_DEC   0x04
+#define LCD_ENTRY_DEC_SHIFT   0x05
+#define LCD_ENTRY_INC_   0x06
+#define LCD_ENTRY_INC_SHIFT   0x07
+#define LCD_DISP_OFF   0x08
+#define LCD_DISP_ON   0x0C
+#define LCD_DISP_ON_BLINK   0x0D
+#define LCD_DISP_ON_CURSOR   0x0E
+#define LCD_DISP_ON_CURSOR_BLINK   0x0F
+#define LCD_MOVE_CURSOR_LEFT   0x10
+#define LCD_MOVE_CURSOR_RIGHT   0x14
+#define LCD_MOVE_DISP_LEFT   0x18
+#define LCD_MOVE_DISP_RIGHT   0x1C
+#define LCD_FUNCTION_4BIT_1LINE   0x20
+#define LCD_FUNCTION_4BIT_2LINES   0x28
+#define LCD_FUNCTION_8BIT_1LINE   0x30
+#define LCD_FUNCTION_8BIT_2LINES   0x38
+#define LCD_MODE_DEFAULT   ((1<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )

Functions

+#define lcd_puts_P(__s)   lcd_puts_p(PSTR(__s))
 macros for automatically storing string constant in program memory
void lcd_init (uint8_t dispAttr)
 Initialize display and select type of cursor.
void lcd_clrscr (void)
 Clear display and set cursor to home position.
void lcd_home (void)
 Set cursor to home position.
void lcd_gotoxy (uint8_t x, uint8_t y)
 Set cursor to specified position.
void lcd_putc (char c)
 Display character at current cursor position.
void lcd_puts (const char *s)
 Display string without auto linefeed.
void lcd_puts_p (const char *progmem_s)
 Display string from program memory without auto linefeed.
void lcd_command (uint8_t cmd)
 Send LCD controller instruction command.
void lcd_data (uint8_t data)
 Send data byte to LCD controller.
+


Define Documentation

+

+ + + + +
+ + + + +
#define XTAL   4000000
+
+ + + + + +
+   + + +

+clock frequency in Hz, used to calculate delay timer

+

+ + + + +
+ + + + +
#define LCD_CONTROLLER_KS0073   0
+
+ + + + + +
+   + + +

+Use 0 for HD44780 controller, 1 for KS0073 controller

+

+ + + + +
+ + + + +
#define LCD_LINES   2
+
+ + + + + +
+   + + +

+number of visible lines of the display

+

+ + + + +
+ + + + +
#define LCD_DISP_LENGTH   16
+
+ + + + + +
+   + + +

+visibles characters per line of the display

+

+ + + + +
+ + + + +
#define LCD_LINE_LENGTH   0x40
+
+ + + + + +
+   + + +

+internal line length of the display

+

+ + + + +
+ + + + +
#define LCD_START_LINE1   0x00
+
+ + + + + +
+   + + +

+DDRAM address of first char of line 1

+

+ + + + +
+ + + + +
#define LCD_START_LINE2   0x40
+
+ + + + + +
+   + + +

+DDRAM address of first char of line 2

+

+ + + + +
+ + + + +
#define LCD_START_LINE3   0x14
+
+ + + + + +
+   + + +

+DDRAM address of first char of line 3

+

+ + + + +
+ + + + +
#define LCD_START_LINE4   0x54
+
+ + + + + +
+   + + +

+DDRAM address of first char of line 4

+

+ + + + +
+ + + + +
#define LCD_WRAP_LINES   0
+
+ + + + + +
+   + + +

+0: no wrap, 1: wrap at end of visibile line

+

+ + + + +
+ + + + +
#define LCD_IO_MODE   1
+
+ + + + + +
+   + + +

+0: memory mapped mode, 1: IO port mode

+

+ + + + +
+ + + + +
#define LCD_PORT   PORTA
+
+ + + + + +
+   + + +

+port for the LCD lines

+

+ + + + +
+ + + + +
#define LCD_DATA0_PORT   LCD_PORT
+
+ + + + + +
+   + + +

+port for 4bit data bit 0

+

+ + + + +
+ + + + +
#define LCD_DATA1_PORT   LCD_PORT
+
+ + + + + +
+   + + +

+port for 4bit data bit 1

+

+ + + + +
+ + + + +
#define LCD_DATA2_PORT   LCD_PORT
+
+ + + + + +
+   + + +

+port for 4bit data bit 2

+

+ + + + +
+ + + + +
#define LCD_DATA3_PORT   LCD_PORT
+
+ + + + + +
+   + + +

+port for 4bit data bit 3

+

+ + + + +
+ + + + +
#define LCD_DATA0_PIN   0
+
+ + + + + +
+   + + +

+pin for 4bit data bit 0

+

+ + + + +
+ + + + +
#define LCD_DATA1_PIN   1
+
+ + + + + +
+   + + +

+pin for 4bit data bit 1

+

+ + + + +
+ + + + +
#define LCD_DATA2_PIN   2
+
+ + + + + +
+   + + +

+pin for 4bit data bit 2

+

+ + + + +
+ + + + +
#define LCD_DATA3_PIN   3
+
+ + + + + +
+   + + +

+pin for 4bit data bit 3

+

+ + + + +
+ + + + +
#define LCD_RS_PORT   LCD_PORT
+
+ + + + + +
+   + + +

+port for RS line

+

+ + + + +
+ + + + +
#define LCD_RS_PIN   4
+
+ + + + + +
+   + + +

+pin for RS line

+

+ + + + +
+ + + + +
#define LCD_RW_PORT   LCD_PORT
+
+ + + + + +
+   + + +

+port for RW line

+

+ + + + +
+ + + + +
#define LCD_RW_PIN   5
+
+ + + + + +
+   + + +

+pin for RW line

+

+ + + + +
+ + + + +
#define LCD_E_PORT   LCD_PORT
+
+ + + + + +
+   + + +

+port for Enable line

+

+ + + + +
+ + + + +
#define LCD_E_PIN   6
+
+ + + + + +
+   + + +

+pin for Enable line

+


Function Documentation

+

+ + + + +
+ + + + + + + + + +
void lcd_init uint8_t  dispAttr  ) 
+
+ + + + + +
+   + + +

+Initialize display and select type of cursor. +

+

Parameters:
+ + +
dispAttr LCD_DISP_OFF display off
+ LCD_DISP_ON display on, cursor off
+ LCD_DISP_ON_CURSOR display on, cursor on
+ LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing
+
+
Returns:
none
+
+

+ + + + +
+ + + + + + + + + +
void lcd_clrscr void   ) 
+
+ + + + + +
+   + + +

+Clear display and set cursor to home position. +

+

Parameters:
+ + +
void 
+
+
Returns:
none
+
+

+ + + + +
+ + + + + + + + + +
void lcd_home void   ) 
+
+ + + + + +
+   + + +

+Set cursor to home position. +

+

Parameters:
+ + +
void 
+
+
Returns:
none
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + +
void lcd_gotoxy uint8_t  x,
uint8_t  y
+
+ + + + + +
+   + + +

+Set cursor to specified position. +

+

Parameters:
+ + + +
x horizontal position
+ (0: left most position)
y vertical position
+ (0: first line)
+
+
Returns:
none
+
+

+ + + + +
+ + + + + + + + + +
void lcd_putc char  c  ) 
+
+ + + + + +
+   + + +

+Display character at current cursor position. +

+

Parameters:
+ + +
c character to be displayed
+
+
Returns:
none
+
+

+ + + + +
+ + + + + + + + + +
void lcd_puts const char *  s  ) 
+
+ + + + + +
+   + + +

+Display string without auto linefeed. +

+

Parameters:
+ + +
s string to be displayed
+
+
Returns:
none
+
+

+ + + + +
+ + + + + + + + + +
void lcd_puts_p const char *  progmem_s  ) 
+
+ + + + + +
+   + + +

+Display string from program memory without auto linefeed. +

+

Parameters:
+ + +
s string from program memory be be displayed
+
+
Returns:
none
+
See also:
lcd_puts_P
+
+

+ + + + +
+ + + + + + + + + +
void lcd_command uint8_t  cmd  ) 
+
+ + + + + +
+   + + +

+Send LCD controller instruction command. +

+

Parameters:
+ + +
cmd instruction to send to LCD controller, see HD44780 data sheet
+
+
Returns:
none
+
+

+ + + + +
+ + + + + + + + + +
void lcd_data uint8_t  data  ) 
+
+ + + + + +
+   + + +

+Send data byte to LCD controller. +

+Similar to lcd_putc(), but without interpreting LF

Parameters:
+ + +
data byte to send to LCD controller, see HD44780 data sheet
+
+
Returns:
none
+
+


Generated on Mon Jan 30 20:50:15 2006 for AVR-GCC libraries by  + +doxygen 1.4.5
+ + diff --git a/freq-counter/lcdlibrary/lcd.c b/freq-counter/lcdlibrary/lcd.c new file mode 100644 index 0000000..edaf65f --- /dev/null +++ b/freq-counter/lcdlibrary/lcd.c @@ -0,0 +1,609 @@ +/**************************************************************************** + Title : HD44780U LCD library + Author: Peter Fleury http://jump.to/fleury + File: $Id: lcd.c,v 1.14.2.1 2006/01/29 12:16:41 peter Exp $ + Software: AVR-GCC 3.3 + Target: any AVR device, memory mapped mode only for AT90S4414/8515/Mega + + DESCRIPTION + Basic routines for interfacing a HD44780U-based text lcd display + + Originally based on Volker Oth's lcd library, + changed lcd_init(), added additional constants for lcd_command(), + added 4-bit I/O mode, improved and optimized code. + + Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in + 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported. + + Memory mapped mode compatible with Kanda STK200, but supports also + generation of R/W signal through A8 address line. + + USAGE + See the C include lcd.h file for a description of each function + +*****************************************************************************/ +#include +#include +#include +#include "lcd.h" + + + +/* +** constants/macros +*/ +#define DDR(x) (*(&x - 1)) /* address of data direction register of port x */ +#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) + /* on ATmega64/128 PINF is on port 0x00 and not 0x60 */ + #define PIN(x) ( &PORTF==&(x) ? _SFR_IO8(0x00) : (*(&x - 2)) ) +#else + #define PIN(x) (*(&x - 2)) /* address of input register of port x */ +#endif + + +#if LCD_IO_MODE +#define lcd_e_delay() __asm__ __volatile__( "rjmp 1f\n 1:" ); +#define lcd_e_high() LCD_E_PORT |= _BV(LCD_E_PIN); +#define lcd_e_low() LCD_E_PORT &= ~_BV(LCD_E_PIN); +#define lcd_e_toggle() toggle_e() +#define lcd_rw_high() LCD_RW_PORT |= _BV(LCD_RW_PIN) +#define lcd_rw_low() LCD_RW_PORT &= ~_BV(LCD_RW_PIN) +#define lcd_rs_high() LCD_RS_PORT |= _BV(LCD_RS_PIN) +#define lcd_rs_low() LCD_RS_PORT &= ~_BV(LCD_RS_PIN) +#endif + +#if LCD_IO_MODE +#if LCD_LINES==1 +#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE +#else +#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES +#endif +#else +#if LCD_LINES==1 +#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_1LINE +#else +#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_2LINES +#endif +#endif + +#if LCD_CONTROLLER_KS0073 +#if LCD_LINES==4 + +#define KS0073_EXTENDED_FUNCTION_REGISTER_ON 0x24 /* |0|010|0100 4-bit mode extension-bit RE = 1 */ +#define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x20 /* |0|000|1001 4 lines mode */ +#define KS0073_4LINES_MODE 0x09 /* |0|001|0000 4-bit mode, extension-bit RE = 0 */ + +#endif +#endif + +/* +** function prototypes +*/ +#if LCD_IO_MODE +static void toggle_e(void); +#endif + +/* +** local functions +*/ + + + +/************************************************************************* + delay loop for small accurate delays: 16-bit counter, 4 cycles/loop +*************************************************************************/ +static inline void _delayFourCycles(unsigned int __count) +{ + if ( __count == 0 ) + __asm__ __volatile__( "rjmp 1f\n 1:" ); // 2 cycles + else + __asm__ __volatile__ ( + "1: sbiw %0,1" "\n\t" + "brne 1b" // 4 cycles/loop + : "=w" (__count) + : "0" (__count) + ); +} + + +/************************************************************************* +delay for a minimum of microseconds +the number of loops is calculated at compile-time from MCU clock frequency +*************************************************************************/ +#define delay(us) _delayFourCycles( ( ( 1*(XTAL/4000) )*us)/1000 ) + + +#if LCD_IO_MODE +/* toggle Enable Pin to initiate write */ +static void toggle_e(void) +{ + lcd_e_high(); + lcd_e_delay(); + lcd_e_low(); +} +#endif + + +/************************************************************************* +Low-level function to write byte to LCD controller +Input: data byte to write to LCD + rs 1: write data + 0: write instruction +Returns: none +*************************************************************************/ +#if LCD_IO_MODE +static void lcd_write(uint8_t data,uint8_t rs) +{ + unsigned char dataBits ; + + + if (rs) { /* write data (RS=1, RW=0) */ + lcd_rs_high(); + } else { /* write instruction (RS=0, RW=0) */ + lcd_rs_low(); + } + lcd_rw_low(); + + if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT ) + && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) ) + { + /* configure data pins as output */ + DDR(LCD_DATA0_PORT) |= 0x0F; + + /* output high nibble first */ + dataBits = LCD_DATA0_PORT & 0xF0; + LCD_DATA0_PORT = dataBits |((data>>4)&0x0F); + lcd_e_toggle(); + + /* output low nibble */ + LCD_DATA0_PORT = dataBits | (data&0x0F); + lcd_e_toggle(); + + /* all data pins high (inactive) */ + LCD_DATA0_PORT = dataBits | 0x0F; + } + else + { + /* configure data pins as output */ + DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); + DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); + DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); + DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); + + /* output high nibble first */ + LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); + LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); + LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); + if(data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + if(data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + if(data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + if(data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + lcd_e_toggle(); + + /* output low nibble */ + LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); + LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); + LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); + if(data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + if(data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + if(data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + if(data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + lcd_e_toggle(); + + /* all data pins high (inactive) */ + LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + } +} +#else +#define lcd_write(d,rs) if (rs) *(volatile uint8_t*)(LCD_IO_DATA) = d; else *(volatile uint8_t*)(LCD_IO_FUNCTION) = d; +/* rs==0 -> write instruction to LCD_IO_FUNCTION */ +/* rs==1 -> write data to LCD_IO_DATA */ +#endif + + +/************************************************************************* +Low-level function to read byte from LCD controller +Input: rs 1: read data + 0: read busy flag / address counter +Returns: byte read from LCD controller +*************************************************************************/ +#if LCD_IO_MODE +static uint8_t lcd_read(uint8_t rs) +{ + uint8_t data; + + + if (rs) + lcd_rs_high(); /* RS=1: read data */ + else + lcd_rs_low(); /* RS=0: read busy flag */ + lcd_rw_high(); /* RW=1 read mode */ + + if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT ) + && ( LCD_DATA0_PIN == 0 )&& (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) ) + { + DDR(LCD_DATA0_PORT) &= 0xF0; /* configure data pins as input */ + + lcd_e_high(); + lcd_e_delay(); + data = PIN(LCD_DATA0_PORT) << 4; /* read high nibble first */ + lcd_e_low(); + + lcd_e_delay(); /* Enable 500ns low */ + + lcd_e_high(); + lcd_e_delay(); + data |= PIN(LCD_DATA0_PORT)&0x0F; /* read low nibble */ + lcd_e_low(); + } + else + { + /* configure data pins as input */ + DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN); + DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN); + DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN); + DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN); + + /* read high nibble first */ + lcd_e_high(); + lcd_e_delay(); + data = 0; + if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x10; + if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x20; + if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x40; + if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x80; + lcd_e_low(); + + lcd_e_delay(); /* Enable 500ns low */ + + /* read low nibble */ + lcd_e_high(); + lcd_e_delay(); + if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x01; + if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x02; + if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x04; + if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x08; + lcd_e_low(); + } + return data; +} +#else +#define lcd_read(rs) (rs) ? *(volatile uint8_t*)(LCD_IO_DATA+LCD_IO_READ) : *(volatile uint8_t*)(LCD_IO_FUNCTION+LCD_IO_READ) +/* rs==0 -> read instruction from LCD_IO_FUNCTION */ +/* rs==1 -> read data from LCD_IO_DATA */ +#endif + + +/************************************************************************* +loops while lcd is busy, returns address counter +*************************************************************************/ +static uint8_t lcd_waitbusy(void) + +{ + register uint8_t c; + + /* wait until busy flag is cleared */ + while ( (c=lcd_read(0)) & (1<= LCD_START_LINE2) && (pos < LCD_START_LINE3) ) + addressCounter = LCD_START_LINE3; + else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4) ) + addressCounter = LCD_START_LINE4; + else + addressCounter = LCD_START_LINE1; +#else + if ( pos < LCD_START_LINE3 ) + addressCounter = LCD_START_LINE2; + else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4) ) + addressCounter = LCD_START_LINE3; + else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) ) + addressCounter = LCD_START_LINE4; + else + addressCounter = LCD_START_LINE1; +#endif +#endif + lcd_command((1<>4; + LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // _BV(LCD_FUNCTION_8BIT)>>4; + lcd_e_toggle(); + delay(4992); /* delay, busy flag can't be checked here */ + + /* repeat last command */ + lcd_e_toggle(); + delay(64); /* delay, busy flag can't be checked here */ + + /* repeat last command a third time */ + lcd_e_toggle(); + delay(64); /* delay, busy flag can't be checked here */ + + /* now configure for 4bit mode */ + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // LCD_FUNCTION_4BIT_1LINE>>4 + lcd_e_toggle(); + delay(64); /* some displays need this additional delay */ + + /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */ +#else + /* + * Initialize LCD to 8 bit memory mapped mode + */ + + /* enable external SRAM (memory mapped lcd) and one wait state */ + MCUCR = _BV(SRE) | _BV(SRW); + + /* reset LCD */ + delay(16000); /* wait 16ms after power-on */ + lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ + delay(4992); /* wait 5ms */ + lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ + delay(64); /* wait 64us */ + lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ + delay(64); /* wait 64us */ +#endif + +#if KS0073_4LINES_MODE + /* Display with KS0073 controller requires special commands for enabling 4 line mode */ + lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON); + lcd_command(KS0073_4LINES_MODE); + lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF); +#else + lcd_command(LCD_FUNCTION_DEFAULT); /* function set: display lines */ +#endif + lcd_command(LCD_DISP_OFF); /* display off */ + lcd_clrscr(); /* display clear */ + lcd_command(LCD_MODE_DEFAULT); /* set entry mode */ + lcd_command(dispAttr); /* display/cursor control */ + +}/* lcd_init */ diff --git a/freq-counter/lcdlibrary/lcd.h b/freq-counter/lcdlibrary/lcd.h new file mode 100644 index 0000000..927fb65 --- /dev/null +++ b/freq-counter/lcdlibrary/lcd.h @@ -0,0 +1,265 @@ +#ifndef LCD_H +#define LCD_H +/************************************************************************* + Title : C include file for the HD44780U LCD library (lcd.c) + Author: Peter Fleury http://jump.to/fleury + File: $Id: lcd.h,v 1.13.2.2 2006/01/30 19:51:33 peter Exp $ + Software: AVR-GCC 3.3 + Hardware: any AVR device, memory mapped mode only for AT90S4414/8515/Mega +***************************************************************************/ + +/** + @defgroup pfleury_lcd LCD library + @code #include @endcode + + @brief Basic routines for interfacing a HD44780U-based text LCD display + + Originally based on Volker Oth's LCD library, + changed lcd_init(), added additional constants for lcd_command(), + added 4-bit I/O mode, improved and optimized code. + + Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in + 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported. + + Memory mapped mode compatible with Kanda STK200, but supports also + generation of R/W signal through A8 address line. + + @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury + + @see The chapter Interfacing a HD44780 Based LCD to an AVR + on my home page. + +*/ + +/*@{*/ + +#if (__GNUC__ * 100 + __GNUC_MINOR__) < 303 +#error "This library requires AVR-GCC 3.3 or later, update to newer AVR-GCC compiler !" +#endif + +#include +#include + +/** + * @name Definitions for MCU Clock Frequency + * Adapt the MCU clock frequency in Hz to your target. + */ +#define XTAL 4000000 /**< clock frequency in Hz, used to calculate delay timer */ + + +/** + * @name Definition for LCD controller type + * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller. + */ +#define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */ + +/** + * @name Definitions for Display Size + * Change these definitions to adapt setting to your display + */ +#define LCD_LINES 2 /**< number of visible lines of the display */ +#define LCD_DISP_LENGTH 16 /**< visibles characters per line of the display */ +#define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */ +#define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ +#define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ +#define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ +#define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ +#define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */ + + +#define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */ +#if LCD_IO_MODE +/** + * @name Definitions for 4-bit IO mode + * Change LCD_PORT if you want to use a different port for the LCD pins. + * + * The four LCD data lines and the three control lines RS, RW, E can be on the + * same port or on different ports. + * Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on + * different ports. + * + * Normally the four data lines should be mapped to bit 0..3 on one port, but it + * is possible to connect these data lines in different order or even on different + * ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions. + * + */ +#define LCD_PORT PORTA /**< port for the LCD lines */ +#define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */ +#define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */ +#define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ +#define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ +#define LCD_DATA0_PIN 0 /**< pin for 4bit data bit 0 */ +#define LCD_DATA1_PIN 1 /**< pin for 4bit data bit 1 */ +#define LCD_DATA2_PIN 2 /**< pin for 4bit data bit 2 */ +#define LCD_DATA3_PIN 3 /**< pin for 4bit data bit 3 */ +#define LCD_RS_PORT LCD_PORT /**< port for RS line */ +#define LCD_RS_PIN 4 /**< pin for RS line */ +#define LCD_RW_PORT LCD_PORT /**< port for RW line */ +#define LCD_RW_PIN 5 /**< pin for RW line */ +#define LCD_E_PORT LCD_PORT /**< port for Enable line */ +#define LCD_E_PIN 6 /**< pin for Enable line */ + +#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || \ + defined(__AVR_ATmega8515__)|| defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || \ + defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__) +/* + * memory mapped mode is only supported when the device has an external data memory interface + */ +#define LCD_IO_DATA 0xC000 /* A15=E=1, A14=RS=1 */ +#define LCD_IO_FUNCTION 0x8000 /* A15=E=1, A14=RS=0 */ +#define LCD_IO_READ 0x0100 /* A8 =R/W=1 (R/W: 1=Read, 0=Write */ +#else +#error "external data memory interface not available for this device, use 4-bit IO port mode" + +#endif + + +/** + * @name Definitions for LCD command instructions + * The constants define the various LCD controller instructions which can be passed to the + * function lcd_command(), see HD44780 data sheet for a complete description. + */ + +/* instruction register bit positions, see HD44780U data sheet */ +#define LCD_CLR 0 /* DB0: clear display */ +#define LCD_HOME 1 /* DB1: return to home position */ +#define LCD_ENTRY_MODE 2 /* DB2: set entry mode */ +#define LCD_ENTRY_INC 1 /* DB1: 1=increment, 0=decrement */ +#define LCD_ENTRY_SHIFT 0 /* DB2: 1=display shift on */ +#define LCD_ON 3 /* DB3: turn lcd/cursor on */ +#define LCD_ON_DISPLAY 2 /* DB2: turn display on */ +#define LCD_ON_CURSOR 1 /* DB1: turn cursor on */ +#define LCD_ON_BLINK 0 /* DB0: blinking cursor ? */ +#define LCD_MOVE 4 /* DB4: move cursor/display */ +#define LCD_MOVE_DISP 3 /* DB3: move display (0-> cursor) ? */ +#define LCD_MOVE_RIGHT 2 /* DB2: move right (0-> left) ? */ +#define LCD_FUNCTION 5 /* DB5: function set */ +#define LCD_FUNCTION_8BIT 4 /* DB4: set 8BIT mode (0->4BIT mode) */ +#define LCD_FUNCTION_2LINES 3 /* DB3: two lines (0->one line) */ +#define LCD_FUNCTION_10DOTS 2 /* DB2: 5x10 font (0->5x7 font) */ +#define LCD_CGRAM 6 /* DB6: set CG RAM address */ +#define LCD_DDRAM 7 /* DB7: set DD RAM address */ +#define LCD_BUSY 7 /* DB7: LCD is busy */ + +/* set entry mode: display shift on/off, dec/inc cursor move direction */ +#define LCD_ENTRY_DEC 0x04 /* display shift off, dec cursor move dir */ +#define LCD_ENTRY_DEC_SHIFT 0x05 /* display shift on, dec cursor move dir */ +#define LCD_ENTRY_INC_ 0x06 /* display shift off, inc cursor move dir */ +#define LCD_ENTRY_INC_SHIFT 0x07 /* display shift on, inc cursor move dir */ + +/* display on/off, cursor on/off, blinking char at cursor position */ +#define LCD_DISP_OFF 0x08 /* display off */ +#define LCD_DISP_ON 0x0C /* display on, cursor off */ +#define LCD_DISP_ON_BLINK 0x0D /* display on, cursor off, blink char */ +#define LCD_DISP_ON_CURSOR 0x0E /* display on, cursor on */ +#define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char */ + +/* move cursor/shift display */ +#define LCD_MOVE_CURSOR_LEFT 0x10 /* move cursor left (decrement) */ +#define LCD_MOVE_CURSOR_RIGHT 0x14 /* move cursor right (increment) */ +#define LCD_MOVE_DISP_LEFT 0x18 /* shift display left */ +#define LCD_MOVE_DISP_RIGHT 0x1C /* shift display right */ + +/* function set: set interface data length and number of display lines */ +#define LCD_FUNCTION_4BIT_1LINE 0x20 /* 4-bit interface, single line, 5x7 dots */ +#define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line, 5x7 dots */ +#define LCD_FUNCTION_8BIT_1LINE 0x30 /* 8-bit interface, single line, 5x7 dots */ +#define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line, 5x7 dots */ + + +#define LCD_MODE_DEFAULT ((1< +# to submit bug reports. +#AVRDUDE_VERBOSE = -v -v + +AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) +AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) +AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) + + + +# --------------------------------------------------------------------------- + +# Define directories, if needed. +DIRAVR = c:/winavr +DIRAVRBIN = $(DIRAVR)/bin +DIRAVRUTILS = $(DIRAVR)/utils/bin +DIRINC = . +DIRLIB = $(DIRAVR)/avr/lib + + +# Define programs and commands. +SHELL = sh +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +SIZE = avr-size +NM = avr-nm +AVRDUDE = avrdude +REMOVE = rm -f +COPY = cp + + + + +# Define Messages +# English +MSG_ERRORS_NONE = Errors: none +MSG_BEGIN = -------- begin -------- +MSG_END = -------- end -------- +MSG_SIZE_BEFORE = Size before: +MSG_SIZE_AFTER = Size after: +MSG_COFF = Converting to AVR COFF: +MSG_EXTENDED_COFF = Converting to AVR Extended COFF: +MSG_FLASH = Creating load file for Flash: +MSG_EEPROM = Creating load file for EEPROM: +MSG_EXTENDED_LISTING = Creating Extended Listing: +MSG_SYMBOL_TABLE = Creating Symbol Table: +MSG_LINKING = Linking: +MSG_COMPILING = Compiling: +MSG_ASSEMBLING = Assembling: +MSG_CLEANING = Cleaning project: + + + + +# Define all object files. +OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) + +# Define all listing files. +LST = $(ASRC:.S=.lst) $(SRC:.c=.lst) + + +# Compiler flags to generate dependency files. +GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d + + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) +ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) + + + + + +# Default target. +all: begin gccversion sizebefore build sizeafter finished end + +build: elf hex eep lss sym + +elf: $(TARGET).elf +hex: $(TARGET).hex +eep: $(TARGET).eep +lss: $(TARGET).lss +sym: $(TARGET).sym + + + +# Eye candy. +# AVR Studio 3.x does not check make's exit code but relies on +# the following magic strings to be generated by the compile job. +begin: + @echo + @echo $(MSG_BEGIN) + +finished: + @echo $(MSG_ERRORS_NONE) + +end: + @echo $(MSG_END) + @echo + + +# Display size of file. +HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex +ELFSIZE = $(SIZE) -A $(TARGET).elf +sizebefore: + @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi + +sizeafter: + @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi + + + +# Display compiler version information. +gccversion : + @$(CC) --version + + + +# Program the device. +program: $(TARGET).hex $(TARGET).eep + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + + + + +# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. +COFFCONVERT=$(OBJCOPY) --debugging \ +--change-section-address .data-0x800000 \ +--change-section-address .bss-0x800000 \ +--change-section-address .noinit-0x800000 \ +--change-section-address .eeprom-0x810000 + + +coff: $(TARGET).elf + @echo + @echo $(MSG_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-avr $< $(TARGET).cof + + +extcoff: $(TARGET).elf + @echo + @echo $(MSG_EXTENDED_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof + + + +# Create final output files (.hex, .eep) from ELF output file. +%.hex: %.elf + @echo + @echo $(MSG_FLASH) $@ + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +%.eep: %.elf + @echo + @echo $(MSG_EEPROM) $@ + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + +# Create extended listing file from ELF output file. +%.lss: %.elf + @echo + @echo $(MSG_EXTENDED_LISTING) $@ + $(OBJDUMP) -h -S $< > $@ + +# Create a symbol table from ELF output file. +%.sym: %.elf + @echo + @echo $(MSG_SYMBOL_TABLE) $@ + $(NM) -n $< > $@ + + + +# Link: create ELF output file from object files. +.SECONDARY : $(TARGET).elf +.PRECIOUS : $(OBJ) +%.elf: $(OBJ) + @echo + @echo $(MSG_LINKING) $@ + $(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS) + + +# Compile: create object files from C source files. +%.o : %.c + @echo + @echo $(MSG_COMPILING) $< + $(CC) -c $(ALL_CFLAGS) $< -o $@ + + +# Compile: create assembler files from C source files. +%.s : %.c + $(CC) -S $(ALL_CFLAGS) $< -o $@ + + +# Assemble: create object files from assembler source files. +%.o : %.S + @echo + @echo $(MSG_ASSEMBLING) $< + $(CC) -c $(ALL_ASFLAGS) $< -o $@ + + + +# Target: clean project. +clean: begin clean_list finished end + +clean_list : + @echo + @echo $(MSG_CLEANING) + $(REMOVE) $(TARGET).hex + $(REMOVE) $(TARGET).eep + $(REMOVE) $(TARGET).obj + $(REMOVE) $(TARGET).cof + $(REMOVE) $(TARGET).elf + $(REMOVE) $(TARGET).map + $(REMOVE) $(TARGET).obj + $(REMOVE) $(TARGET).a90 + $(REMOVE) $(TARGET).sym + $(REMOVE) $(TARGET).lnk + $(REMOVE) $(TARGET).lss + $(REMOVE) $(OBJ) + $(REMOVE) $(LST) + $(REMOVE) $(SRC:.c=.s) + $(REMOVE) $(SRC:.c=.d) + $(REMOVE) .dep/* + + + +# Include the dependency files. +-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) + + +# Listing of phony targets. +.PHONY : all begin finish end sizebefore sizeafter gccversion \ +build elf hex eep lss sym coff extcoff \ +clean clean_list program + diff --git a/freq-counter/lcdlibrary/test_lcd.c b/freq-counter/lcdlibrary/test_lcd.c new file mode 100644 index 0000000..5b1ae10 --- /dev/null +++ b/freq-counter/lcdlibrary/test_lcd.c @@ -0,0 +1,167 @@ +/************************************************************************* +Title: testing output to a HD44780 based LCD display. +Author: Peter Fleury http://jump.to/fleury +File: $Id: test_lcd.c,v 1.6 2004/12/10 13:53:59 peter Exp $ +Software: AVR-GCC 3.3 +Hardware: HD44780 compatible LCD text display + ATS90S8515/ATmega if memory-mapped LCD interface is used + any AVR with 7 free I/O pins if 4-bit IO port mode is used +**************************************************************************/ +#include +#include +#include +#include "lcd.h" + + +/* +** constant definitions +*/ +static const PROGMEM unsigned char copyRightChar[] = +{ + 0x07, 0x08, 0x13, 0x14, 0x14, 0x13, 0x08, 0x07, + 0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00 +}; + + +/* +** function prototypes +*/ +void wait_until_key_pressed(void); + + +void wait_until_key_pressed(void) +{ + unsigned char temp1, temp2; + unsigned int i; + + do { + temp1 = PIND; // read input + for(i=0;i<65535;i++); + temp2 = PIND; // read input + temp1 = (temp1 & temp2); // debounce input + } while ( temp1 & _BV(PIND2) ); + + loop_until_bit_is_set(PIND,PIND2); /* wait until key is released */ +} + + +int main(void) +{ + char buffer[7]; + int num=134; + unsigned char i; + + + DDRD &=~ (1 << PD2); /* Pin PD2 input */ + PORTD |= (1 << PD2); /* Pin PD2 pull-up enabled */ + + + /* initialize display, cursor off */ + lcd_init(LCD_DISP_ON); + + for (;;) { /* loop forever */ + /* + * Test 1: write text to display + */ + + /* clear display and home cursor */ + lcd_clrscr(); + + /* put string to display (line 1) with linefeed */ + lcd_puts("LCD Test Line 1\n"); + + /* cursor is now on second line, write second line */ + lcd_puts("Line 2"); + + /* move cursor to position 8 on line 2 */ + lcd_gotoxy(7,1); + + /* write single char to display */ + lcd_putc(':'); + + /* wait until push button PD2 (INT0) is pressed */ + wait_until_key_pressed(); + + + /* + * Test 2: use lcd_command() to turn on cursor + */ + + /* turn on cursor */ + lcd_command(LCD_DISP_ON_CURSOR); + + /* put string */ + lcd_puts( "CurOn"); + + /* wait until push button PD2 (INT0) is pressed */ + wait_until_key_pressed(); + + + /* + * Test 3: display shift + */ + + lcd_clrscr(); /* clear display home cursor */ + + /* put string from program memory to display */ + lcd_puts_P( "Line 1 longer than 14 characters\n" ); + lcd_puts_P( "Line 2 longer than 14 characters" ); + + /* move BOTH lines one position to the left */ + lcd_command(LCD_MOVE_DISP_LEFT); + + /* wait until push button PD2 (INT0) is pressed */ + wait_until_key_pressed(); + + /* turn off cursor */ + lcd_command(LCD_DISP_ON); + + + /* + * Test: Display integer values + */ + + lcd_clrscr(); /* clear display home cursor */ + + /* convert interger into string */ + itoa( num , buffer, 10); + + /* put converted string to display */ + lcd_puts(buffer); + + /* wait until push button PD2 (INT0) is pressed */ + wait_until_key_pressed(); + + + /* + * Test: Display userdefined characters + */ + + lcd_clrscr(); /* clear display home cursor */ + + lcd_puts("Copyright: "); + + /* + * load two userdefined characters from program memory + * into LCD controller CG RAM location 0 and 1 + */ + lcd_command(_BV(LCD_CGRAM)); /* set CG RAM start address 0 */ + for(i=0; i<16; i++) + { + lcd_data(pgm_read_byte_near(©RightChar[i])); + } + + /* move cursor to position 0 on line 2 */ + /* Note: this switched back to DD RAM adresses */ + lcd_gotoxy(0,1); + + /* display user defined (c), built using two user defined chars */ + lcd_putc(0); + lcd_putc(1); + + + /* wait until push button PD2 (INT0) is pressed */ + wait_until_key_pressed(); + + } +} diff --git a/freq-counter/ringbuffer.c b/freq-counter/ringbuffer.c new file mode 100644 index 0000000..13c9f42 --- /dev/null +++ b/freq-counter/ringbuffer.c @@ -0,0 +1,89 @@ +#include "ringbuffer.h" + +uint16_t _rb_mod(uint16_t num, uint16_t denom) +{ + for (; num >= denom; num -= denom); + return num; +} + +void ringbuffer_init(ringbuffer *buf, int bufsize) +{ + buf->read_pointer = 0; + buf->write_pointer = 0; + buf->size = bufsize - sizeof(ringbuffer); +} + +uint16_t ringbuffer_canread(ringbuffer *buf) +{ + return _rb_mod(buf->write_pointer + buf->size + buf->size - buf->read_pointer, buf->size); +} + +uint16_t ringbuffer_canwrite(ringbuffer *buf) +{ + return _rb_mod(buf->read_pointer + buf->size + buf->size - buf->write_pointer - 1, buf->size); +} + +uint8_t ringbuffer_readchar(ringbuffer *buf) +{ + uint8_t r = 0; + if (ringbuffer_canread(buf)) + { + r = buf->data[buf->read_pointer]; + buf->read_pointer = _rb_mod(buf->read_pointer + 1, buf->size); + } + return r; +} + +void ringbuffer_writechar(ringbuffer *buf, uint8_t data) +{ + if (ringbuffer_canwrite(buf)) + { + buf->data[buf->write_pointer] = data; + buf->write_pointer = _rb_mod(buf->write_pointer + 1, buf->size); + } +} + + +uint8_t ringbuffer_peekchar(ringbuffer *buf, uint16_t index) +{ + return buf->data[_rb_mod(buf->read_pointer + index, buf->size)]; +} + +uint16_t ringbuffer_readblock(ringbuffer *buf, uint8_t *newbuf, int size) +{ + uint16_t nc, i; + uint8_t *rp, *ms; + if ((nc = ringbuffer_canread(buf)) < size) + size = nc; + if (size) + { + for (i = 0, rp = buf->data + buf->read_pointer, ms = buf->data + buf->size; i < size; i++, rp++) + { + if (rp >= ms) + rp = buf->data; + newbuf[i] = *rp; + } + buf->read_pointer = rp - buf->data; + } + return size; +} + +uint16_t ringbuffer_writeblock(ringbuffer *buf, uint8_t *data, int size) +{ + uint16_t nc, i; + uint8_t *wp, *ms; + + if ((nc = ringbuffer_canwrite(buf)) < size) + size = nc; + if (size) + { + for (i = 0, wp = buf->write_pointer + buf->data, ms = buf->data + buf->size; i < size; i++, wp++) + { + if (wp >= ms) + wp = buf->data; + *wp = data[i]; + } + buf->write_pointer = wp - buf->data; + } + return size; +} diff --git a/freq-counter/ringbuffer.h b/freq-counter/ringbuffer.h new file mode 100644 index 0000000..c6a24f4 --- /dev/null +++ b/freq-counter/ringbuffer.h @@ -0,0 +1,26 @@ +#ifndef _RINGBUFFER_H +#define _RINGBUFFER_H + +#include +#include + +typedef struct { + uint16_t read_pointer; + uint16_t write_pointer; + uint16_t size; + uint8_t data[]; +} ringbuffer; + +void ringbuffer_init(ringbuffer *buf, int bufsize); + +uint16_t ringbuffer_canread(ringbuffer *buf); +uint16_t ringbuffer_canwrite(ringbuffer *buf); + +uint8_t ringbuffer_readchar(ringbuffer *buf); +uint8_t ringbuffer_peekchar(ringbuffer *buf, uint16_t index); +uint16_t ringbuffer_readblock(ringbuffer *buf, uint8_t *newbuf, int size); + +void ringbuffer_writechar(ringbuffer *buf, uint8_t data); +uint16_t ringbuffer_writeblock(ringbuffer *buf, uint8_t *data, int size); + +#endif /* _RINGBUFFER_H */ diff --git a/freq-counter/serial.c b/freq-counter/serial.c new file mode 100644 index 0000000..3a691d6 --- /dev/null +++ b/freq-counter/serial.c @@ -0,0 +1,72 @@ +#include "serial.h" + +#include "ringbuffer.h" + +#define BUFSIZE 64 + sizeof(ringbuffer) +#define BAUD 19200 + +volatile uint8_t _rx_buffer[BUFSIZE]; +volatile uint8_t _tx_buffer[BUFSIZE]; + +void serial_init(uint16_t baud) +{ + ringbuffer_init(rx_buffer, BUFSIZE); + ringbuffer_init(tx_buffer, BUFSIZE); + + UCSR0A = 0; + UCSR0B = (1 << RXEN0) | (1 << TXEN0); + UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); + + UBRR0 = ((F_CPU / 16) / baud) - 1; + + UCSR0B |= (1 << RXCIE0) | (1 << UDRIE0); +} + +ISR(USART_RX_vect) +{ + ringbuffer_writechar(rx_buffer, UDR0); +} + +ISR(USART_UDRE_vect) +{ + if (ringbuffer_canread(tx_buffer)) + { + UDR0 = ringbuffer_readchar(tx_buffer); + } + else + { + UCSR0B &= ~(1 << UDRIE0); + } +} + +uint16_t serial_rxchars() +{ + return ringbuffer_canread(rx_buffer); +} + +uint16_t serial_txchars() +{ + return ringbuffer_canread(tx_buffer); +} + +uint8_t serial_popchar() +{ + return ringbuffer_readchar(rx_buffer); +} + +uint16_t serial_recvblock(uint8_t *block, int blocksize) +{ + return ringbuffer_readblock(rx_buffer, block, blocksize); +} + +void serial_writechar(uint8_t data) +{ + ringbuffer_writechar(tx_buffer, data); + UCSR0B |= (1 << UDRIE0); +} + +void serial_writeblock(uint8_t *data, int datalen) +{ + ringbuffer_writeblock(tx_buffer, data, datalen); + UCSR0B |= (1 << UDRIE0); +} diff --git a/freq-counter/serial.h b/freq-counter/serial.h new file mode 100644 index 0000000..efda9d6 --- /dev/null +++ b/freq-counter/serial.h @@ -0,0 +1,24 @@ +#ifndef _SERIAL_H +#define _SERIAL_H + +#include +#include + +#define rx_buffer ((ringbuffer *) _rx_buffer) +#define tx_buffer ((ringbuffer *) _tx_buffer) + +extern volatile uint8_t _rx_buffer[]; +extern volatile uint8_t _tx_buffer[]; + +void serial_init(uint16_t baud); + +uint16_t serial_rxchars(void); +uint16_t serial_txchars(void); + +uint8_t serial_popchar(void); +void serial_writechar(uint8_t data); + +uint16_t serial_recvblock(uint8_t *block, int blocksize); +void serial_writeblock(uint8_t *data, int datalen); + +#endif /* _SERIAL_H */ diff --git a/freq-counter/uartlibrary.zip b/freq-counter/uartlibrary.zip new file mode 100644 index 0000000000000000000000000000000000000000..a4e78df0da33e151e0e1a3ef2df974c767437e24 GIT binary patch literal 17999 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 PfgK1ZFfuT#bOG@ItLT-; literal 0 HcmV?d00001 diff --git a/freq-counter/uartlibrary/doxygen.css b/freq-counter/uartlibrary/doxygen.css new file mode 100644 index 0000000..8cb8b2e --- /dev/null +++ b/freq-counter/uartlibrary/doxygen.css @@ -0,0 +1,49 @@ +H1 { text-align: center; } +CAPTION { font-weight: bold } +A.qindex {} +A.qindexRef {} +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code { text-decoration: none; font-weight: normal; color: #4444ee } +A.codeRef { font-weight: normal; color: #4444ee } +A:hover { text-decoration: none; background-color: #f2f2ff } +DL.el { margin-left: -1cm } +DIV.fragment { width: 100%; border: none; background-color: #eeeeee } +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #f2f2ff; font-weight: bold; } +TD.mdname1 { background-color: #f2f2ff; font-weight: bold; color: #602020; } +TD.mdname { background-color: #f2f2ff; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold } +DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller } +BODY { background: white; color: black } +TD.indexkey { + background-color: #eeeeff; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} +TD.indexvalue { + background-color: #eeeeff; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} +span.keyword { color: #008000 } +span.keywordtype { color: #604020 } +span.keywordflow { color: #e08000 } +span.comment { color: #800000 } +span.preprocessor { color: #806020 } +span.stringliteral { color: #002080 } +span.charliteral { color: #008080 } diff --git a/freq-counter/uartlibrary/doxygen.png b/freq-counter/uartlibrary/doxygen.png new file mode 100644 index 0000000000000000000000000000000000000000..f0a274bbaffdd67f6d784c894d9cf28729db0e14 GIT binary patch literal 1281 zcmaJ>ZA?>F7(Vx-ms?uoS`b@hdRtpo6o^%HU>M$hfGrBvQnk$LE?p^P!kn&ikhyq! zX~V@&tPF5Qt@V?oTL96Bi%aRiwbe1)9DWQI#?)=HxS7QSw`J`5fAJ*eJbB;uNuKA& zdERDo*{Y<(If(#(B$Lr#;nB(8Y#ia=ZCeW?JfPLuQY`=@cW$k}Rivq|vbxGrRq1Tl9;+(gNt?}UtVKM2`T5t1jLzuL@0UIs`S#vlhl4)^ zLgSYrPj@$+`|j?eSbXTmiHGkWxV8V}BzNR?pl9k_s4pDu9vd5a_UzZEPk)}Ad{AV_ zzddrjrh4=Imr`E06;LY{)YYt?o}L~H@7C}F^WB!Ra=v`Q0bj{>5&$66CWF>mf6vjP z2N>RRY6ZYa=K`76>+|_)Xdwko+7wv}7cN|btOhWb(*{sta~6b?S8Omrxw}!4`NhGr zZVpNqpu1@BE`QGWNTpEpcJVW5izu~2B^GlM?1(OPg)zwW;QcP@Ltcclm>XbJL9C|j z=9!2?ua=uIlf0%AndzHsRC}IyTL$EhAee(fdKB`?27KeS^2M8M_7b~PiCFO&r5LC7 z7gl1*a<8;SjNaw#h=843_AV9iZbWQOAp5YOC^&_F*9K0> zB|6%IDb?aM#3viTxkLU4aXg&@+CkNTOnQ1iMP*^?b|^lJy$4C)Zk4isV!|RZ*XhXh zw8q3$=*0LeGC!XI_Wc?dkT~3+*Gu%%yIqP+Wr3H$=&ROMQU6q}Ag^P~>c5vAEO;a- z_dK-3PPeKar%)6$j~vI2#*-YH!1h6HYVtwCX5_wM`iF#UKz&&@9Oo5w3%XGYrX zW>dY~)SG-((Yim%`InwgTvyRC?e=Wh^8KCao!R6Eg&TpVWUY1sN~4G}V?nFnEGo-; zHZ_$eW9-GnC%^WS9b z@p;-$oH#MtC0v>Q$HX%4^JdFdO$0cbv-W)Q TtK}Eh@>>I#ipmV1>S*>q-hkC} literal 0 HcmV?d00001 diff --git a/freq-counter/uartlibrary/group__pfleury__uart.html b/freq-counter/uartlibrary/group__pfleury__uart.html new file mode 100644 index 0000000..7ab9c45 --- /dev/null +++ b/freq-counter/uartlibrary/group__pfleury__uart.html @@ -0,0 +1,560 @@ + + +AVR-GCC libraries: UART Library + + + +

UART Library


Detailed Description

+Interrupt UART library using the built-in UART with transmit and receive circular buffers. +

+

 #include <uart.h> 
+

+This library can be used to transmit and receive data through the built in UART.

+An interrupt is generated when the UART has finished transmitting or receiving a byte. The interrupt handling routines use circular buffers for buffering received and transmitted data.

+The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define the size of the circular buffers in bytes. Note that these constants must be a power of 2. You may need to adapt this constants to your target and your application by adding CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_RX_BUFFER_SIZE=nn to your Makefile.

+

Note:
Based on Atmel Application Note AVR306
+
Author:
Peter Fleury pfleury@gmx.ch http://jump.to/fleury
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Defines

#define UART_BAUD_SELECT(baudRate, xtalCpu)   ((xtalCpu)/((baudRate)*16l)-1)
 UART Baudrate Expression.
#define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate, xtalCpu)   (((xtalCpu)/((baudRate)*8l)-1)|0x8000)
 UART Baudrate Expression for ATmega double speed mode.
#define UART_RX_BUFFER_SIZE   32
#define UART_TX_BUFFER_SIZE   32
+#define UART_FRAME_ERROR   0x0800
+#define UART_OVERRUN_ERROR   0x0400
+#define UART_BUFFER_OVERFLOW   0x0200
+#define UART_NO_DATA   0x0100
+#define uart_puts_P(__s)   uart_puts_p(PSTR(__s))
 Macro to automatically put a string constant into program memory.
+#define uart1_puts_P(__s)   uart1_puts_p(PSTR(__s))
 Macro to automatically put a string constant into program memory.

Functions

void uart_init (unsigned int baudrate)
 Initialize UART and set baudrate.
unsigned int uart_getc (void)
 Get received byte from ringbuffer.
void uart_putc (unsigned char data)
 Put byte to ringbuffer for transmitting via UART.
void uart_puts (const char *s)
 Put string to ringbuffer for transmitting via UART.
void uart_puts_p (const char *s)
 Put string from program memory to ringbuffer for transmitting via UART.
void uart1_init (unsigned int baudrate)
 Initialize USART1 (only available on selected ATmegas).
unsigned int uart1_getc (void)
 Get received byte of USART1 from ringbuffer. (only available on selected ATmega).
void uart1_putc (unsigned char data)
 Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega).
void uart1_puts (const char *s)
 Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega).
void uart1_puts_p (const char *s)
 Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega).
+


Define Documentation

+

+ + + + +
+ + + + + + + + + + + + +
#define UART_BAUD_SELECT baudRate,
xtalCpu   )    ((xtalCpu)/((baudRate)*16l)-1)
+
+ + + + + +
+   + + +

+UART Baudrate Expression. +

+

Parameters:
+ + + +
xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz
baudrate baudrate in bps, e.g. 1200, 2400, 9600
+
+
+

+ + + + +
+ + + + + + + + + + + + +
#define UART_BAUD_SELECT_DOUBLE_SPEED baudRate,
xtalCpu   )    (((xtalCpu)/((baudRate)*8l)-1)|0x8000)
+
+ + + + + +
+   + + +

+UART Baudrate Expression for ATmega double speed mode. +

+

Parameters:
+ + + +
xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz
baudrate baudrate in bps, e.g. 1200, 2400, 9600
+
+
+

+ + + + +
+ + + + +
#define UART_RX_BUFFER_SIZE   32
+
+ + + + + +
+   + + +

+Size of the circular receive buffer, must be power of 2

+

+ + + + +
+ + + + +
#define UART_TX_BUFFER_SIZE   32
+
+ + + + + +
+   + + +

+Size of the circular transmit buffer, must be power of 2

+


Function Documentation

+

+ + + + +
+ + + + + + + + + +
void uart_init unsigned int  baudrate  ) 
+
+ + + + + +
+   + + +

+Initialize UART and set baudrate. +

+

Parameters:
+ + +
baudrate Specify baudrate using macro UART_BAUD_SELECT()
+
+
Returns:
none
+
+

+ + + + +
+ + + + + + + + + +
unsigned int uart_getc void   ) 
+
+ + + + + +
+   + + +

+Get received byte from ringbuffer. +

+Returns in the lower byte the received character and in the higher byte the last receive error. UART_NO_DATA is returned when no data is available.

+

Parameters:
+ + +
void 
+
+
Returns:
lower byte: received byte from ringbuffer

+higher byte: last receive status

    +
  • 0 successfully received data from UART
  • UART_NO_DATA
    +no receive data available
  • UART_BUFFER_OVERFLOW
    +Receive ringbuffer overflow. We are not reading the receive buffer fast enough, one or more received character have been dropped
  • UART_OVERRUN_ERROR
    +Overrun condition by UART. A character already present in the UART UDR register was not read by the interrupt handler before the next character arrived, one or more received characters have been dropped.
  • UART_FRAME_ERROR
    +Framing Error by UART
+
+
+

+ + + + +
+ + + + + + + + + +
void uart_putc unsigned char  data  ) 
+
+ + + + + +
+   + + +

+Put byte to ringbuffer for transmitting via UART. +

+

Parameters:
+ + +
data byte to be transmitted
+
+
Returns:
none
+
+

+ + + + +
+ + + + + + + + + +
void uart_puts const char *  s  ) 
+
+ + + + + +
+   + + +

+Put string to ringbuffer for transmitting via UART. +

+The string is buffered by the uart library in a circular buffer and one character at a time is transmitted to the UART using interrupts. Blocks if it can not write the whole string into the circular buffer.

+

Parameters:
+ + +
s string to be transmitted
+
+
Returns:
none
+
+

+ + + + +
+ + + + + + + + + +
void uart_puts_p const char *  s  ) 
+
+ + + + + +
+   + + +

+Put string from program memory to ringbuffer for transmitting via UART. +

+The string is buffered by the uart library in a circular buffer and one character at a time is transmitted to the UART using interrupts. Blocks if it can not write the whole string into the circular buffer.

+

Parameters:
+ + +
s program memory string to be transmitted
+
+
Returns:
none
+
See also:
uart_puts_P
+
+

+ + + + +
+ + + + + + + + + +
void uart1_init unsigned int  baudrate  ) 
+
+ + + + + +
+   + + +

+Initialize USART1 (only available on selected ATmegas). +

+

See also:
uart_init
+
+

+ + + + +
+ + + + + + + + + +
unsigned int uart1_getc void   ) 
+
+ + + + + +
+   + + +

+Get received byte of USART1 from ringbuffer. (only available on selected ATmega). +

+

See also:
uart_getc
+
+

+ + + + +
+ + + + + + + + + +
void uart1_putc unsigned char  data  ) 
+
+ + + + + +
+   + + +

+Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega). +

+

See also:
uart_putc
+
+

+ + + + +
+ + + + + + + + + +
void uart1_puts const char *  s  ) 
+
+ + + + + +
+   + + +

+Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega). +

+

See also:
uart_puts
+
+

+ + + + +
+ + + + + + + + + +
void uart1_puts_p const char *  s  ) 
+
+ + + + + +
+   + + +

+Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega). +

+

See also:
uart_puts_p
+
+


Generated on Sun Jul 10 13:47:45 2005 for AVR-GCC libraries by  + +doxygen 1.4.1
+ + diff --git a/freq-counter/uartlibrary/makefile b/freq-counter/uartlibrary/makefile new file mode 100644 index 0000000..b90c0c4 --- /dev/null +++ b/freq-counter/uartlibrary/makefile @@ -0,0 +1,508 @@ +# ---------------------------------------------------------------------------- +# Makefile to compile and link the UART library and test program +# Author: Peter Fleury +# File: $Id: makefile.uart,v 1.3 2005/04/09 07:56:09 Peter Exp $ +# based on WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al. +# +# Adjust F_CPU below to the clock frequency in Mhz of your AVR target +# +# Adjust the size of the receive and transmit ringbuffer in bytes using the +# defines -DUART_RX_BUFFER_SIZE=128 and -DUART_TX_BUFFER_SIZE=128 in the +# CDEF section below +# +#---------------------------------------------------------------------------- +# On command line: +# +# make all = Make software. +# +# make clean = Clean out built project files. +# +# make coff = Convert ELF to AVR COFF. +# +# make extcoff = Convert ELF to AVR Extended COFF. +# +# make program = Download the hex file to the device, using avrdude. +# Please customize the avrdude settings below first! +# +# make debug = Start either simulavr or avarice as specified for debugging, +# with avr-gdb or avr-insight as the front end for debugging. +# +# make filename.s = Just compile filename.c into the assembler code only. +# +# make filename.i = Create a preprocessed source file for use in submitting +# bug reports to the GCC project. +# +# To rebuild project do "make clean" then "make all". +#---------------------------------------------------------------------------- + + +# MCU name +MCU = at90s8515 + + +# Processor frequency. +# This will define a symbol, F_CPU, in all source code files equal to the +# processor frequency. You can then use this symbol in your source code to +# calculate timings. Do NOT tack on a 'UL' at the end, this will be done +# automatically to create a 32-bit value in your source code. +F_CPU = 4000000 + + +# Output format. (can be srec, ihex, binary) +FORMAT = ihex + + +# Target file name (without extension). +TARGET = test_uart + + +# List C source files here. (C dependencies are automatically generated.) +SRC = $(TARGET).c uart.c + + +# List Assembler source files here. +# Make them always end in a capital .S. Files ending in a lowercase .s +# will not be considered source files but generated files (assembler +# output from the compiler), and will be deleted upon "make clean"! +# Even though the DOS/Win* filesystem matches both .s and .S the same, +# it will preserve the spelling of the filenames, and gcc itself does +# care about how the name is spelled on its command-line. +ASRC = + + +# Optimization level, can be [0, 1, 2, 3, s]. +# 0 = turn off optimization. s = optimize for size. +# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) +OPT = s + + +# Debugging format. +# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs. +# AVR Studio 4.10 requires dwarf-2. +# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run. +DEBUG = dwarf-2 + + +# List any extra directories to look for include files here. +# Each directory must be seperated by a space. +# Use forward slashes for directory separators. +# For a directory that has spaces, enclose it in quotes. +EXTRAINCDIRS = + + +# Compiler flag to set the C Standard level. +# c89 = "ANSI" C +# gnu89 = c89 plus GCC extensions +# c99 = ISO C99 standard (not yet fully implemented) +# gnu99 = c99 plus GCC extensions +CSTANDARD = -std=gnu99 + + +# Place -D or -U options here +CDEFS = -DF_CPU=$(F_CPU)UL + +# uncomment and adapt these line if you want different UART library buffer size +#CDEFS += -DUART_RX_BUFFER_SIZE=128 +#CDEFS += -DUART_TX_BUFFER_SIZE=128 + + +# Place -I options here +CINCS = + + + +#---------------- Compiler Options ---------------- +# -g*: generate debugging information +# -O*: optimization level +# -f...: tuning, see GCC manual and avr-libc documentation +# -Wall...: warning level +# -Wa,...: tell GCC to pass this to the assembler. +# -adhlns...: create assembler listing +CFLAGS = -g$(DEBUG) +CFLAGS += $(CDEFS) $(CINCS) +CFLAGS += -O$(OPT) +CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CFLAGS += -Wall -Wstrict-prototypes +CFLAGS += -Wa,-adhlns=$(<:.c=.lst) +CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) +CFLAGS += $(CSTANDARD) + + +#---------------- Assembler Options ---------------- +# -Wa,...: tell GCC to pass this to the assembler. +# -ahlms: create listing +# -gstabs: have the assembler create line number information; note that +# for use in COFF files, additional information about filenames +# and function names needs to be present in the assembler source +# files -- see avr-libc docs [FIXME: not yet described there] +ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs + + +#---------------- Library Options ---------------- +# Minimalistic printf version +PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min + +# Floating point printf version (requires MATH_LIB = -lm below) +PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt + +# If this is left blank, then it will use the Standard printf version. +PRINTF_LIB = +#PRINTF_LIB = $(PRINTF_LIB_MIN) +#PRINTF_LIB = $(PRINTF_LIB_FLOAT) + + +# Minimalistic scanf version +SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min + +# Floating point + %[ scanf version (requires MATH_LIB = -lm below) +SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt + +# If this is left blank, then it will use the Standard scanf version. +SCANF_LIB = +#SCANF_LIB = $(SCANF_LIB_MIN) +#SCANF_LIB = $(SCANF_LIB_FLOAT) + + +MATH_LIB = -lm + + + +#---------------- External Memory Options ---------------- + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# used for variables (.data/.bss) and heap (malloc()). +#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# only used for heap (malloc()). +#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff + +EXTMEMOPTS = + + + +#---------------- Linker Options ---------------- +# -Wl,...: tell GCC to pass this to linker. +# -Map: create map file +# --cref: add cross reference to map file +LDFLAGS = -Wl,-Map=$(TARGET).map,--cref +LDFLAGS += $(EXTMEMOPTS) +LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) + + + +#---------------- Programming Options (avrdude) ---------------- + +# Programming hardware: alf avr910 avrisp bascom bsd +# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500 +# +# Type: avrdude -c ? +# to get a full listing. +# +AVRDUDE_PROGRAMMER = stk500 + +# com1 = serial port. Use lpt1 to connect to parallel port. +AVRDUDE_PORT = com1 # programmer connected to serial device + +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep + + +# Uncomment the following if you want avrdude's erase cycle counter. +# Note that this counter needs to be initialized first using -Yn, +# see avrdude manual. +#AVRDUDE_ERASE_COUNTER = -y + +# Uncomment the following if you do /not/ wish a verification to be +# performed after programming the device. +#AVRDUDE_NO_VERIFY = -V + +# Increase verbosity level. Please use this when submitting bug +# reports about avrdude. See +# to submit bug reports. +#AVRDUDE_VERBOSE = -v -v + +AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) +AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) +AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) + + + +#---------------- Debugging Options ---------------- + +# For simulavr only - target MCU frequency. +DEBUG_MFREQ = $(F_CPU) + +# Set the DEBUG_UI to either gdb or insight. +# DEBUG_UI = gdb +DEBUG_UI = insight + +# Set the debugging back-end to either avarice, simulavr. +DEBUG_BACKEND = avarice +#DEBUG_BACKEND = simulavr + +# GDB Init Filename. +GDBINIT_FILE = __avr_gdbinit + +# When using avarice settings for the JTAG +JTAG_DEV = /dev/com1 + +# Debugging port used to communicate between GDB / avarice / simulavr. +DEBUG_PORT = 4242 + +# Debugging host used to communicate between GDB / avarice / simulavr, normally +# just set to localhost unless doing some sort of crazy debugging when +# avarice is running on a different computer. +DEBUG_HOST = localhost + + + +#============================================================================ + + +# Define programs and commands. +SHELL = sh +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +SIZE = avr-size +NM = avr-nm +AVRDUDE = avrdude +REMOVE = rm -f +COPY = cp +WINSHELL = cmd + + +# Define Messages +# English +MSG_ERRORS_NONE = Errors: none +MSG_BEGIN = -------- begin -------- +MSG_END = -------- end -------- +MSG_SIZE_BEFORE = Size before: +MSG_SIZE_AFTER = Size after: +MSG_COFF = Converting to AVR COFF: +MSG_EXTENDED_COFF = Converting to AVR Extended COFF: +MSG_FLASH = Creating load file for Flash: +MSG_EEPROM = Creating load file for EEPROM: +MSG_EXTENDED_LISTING = Creating Extended Listing: +MSG_SYMBOL_TABLE = Creating Symbol Table: +MSG_LINKING = Linking: +MSG_COMPILING = Compiling: +MSG_ASSEMBLING = Assembling: +MSG_CLEANING = Cleaning project: + + + + +# Define all object files. +OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) + +# Define all listing files. +LST = $(SRC:.c=.lst) $(ASRC:.S=.lst) + + +# Compiler flags to generate dependency files. +GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d + + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) +ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) + + + + + +# Default target. +all: begin gccversion sizebefore build sizeafter end + +build: elf hex eep lss sym + +elf: $(TARGET).elf +hex: $(TARGET).hex +eep: $(TARGET).eep +lss: $(TARGET).lss +sym: $(TARGET).sym + + + +# Eye candy. +# AVR Studio 3.x does not check make's exit code but relies on +# the following magic strings to be generated by the compile job. +begin: + @echo + @echo $(MSG_BEGIN) + +end: + @echo $(MSG_END) + @echo + + +# Display size of file. +HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex +ELFSIZE = $(SIZE) -A $(TARGET).elf +AVRMEM = avr-mem.sh $(TARGET).elf $(MCU) + +sizebefore: + @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \ + $(AVRMEM) 2>/dev/null; echo; fi + +sizeafter: + @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \ + $(AVRMEM) 2>/dev/null; echo; fi + + + +# Display compiler version information. +gccversion : + @$(CC) --version + + + +# Program the device. +program: $(TARGET).hex $(TARGET).eep + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + + +# Generate avr-gdb config/init file which does the following: +# define the reset signal, load the target file, connect to target, and set +# a breakpoint at main(). +gdb-config: + @$(REMOVE) $(GDBINIT_FILE) + @echo define reset >> $(GDBINIT_FILE) + @echo SIGNAL SIGHUP >> $(GDBINIT_FILE) + @echo end >> $(GDBINIT_FILE) + @echo file $(TARGET).elf >> $(GDBINIT_FILE) + @echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE) +ifeq ($(DEBUG_BACKEND),simulavr) + @echo load >> $(GDBINIT_FILE) +endif + @echo break main >> $(GDBINIT_FILE) + +debug: gdb-config $(TARGET).elf +ifeq ($(DEBUG_BACKEND), avarice) + @echo Starting AVaRICE - Press enter when "waiting to connect" message displays. + @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \ + $(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT) + @$(WINSHELL) /c pause + +else + @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \ + $(DEBUG_MFREQ) --port $(DEBUG_PORT) +endif + @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE) + + + + +# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. +COFFCONVERT=$(OBJCOPY) --debugging \ +--change-section-address .data-0x800000 \ +--change-section-address .bss-0x800000 \ +--change-section-address .noinit-0x800000 \ +--change-section-address .eeprom-0x810000 + + +coff: $(TARGET).elf + @echo + @echo $(MSG_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-avr $< $(TARGET).cof + + +extcoff: $(TARGET).elf + @echo + @echo $(MSG_EXTENDED_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof + + + +# Create final output files (.hex, .eep) from ELF output file. +%.hex: %.elf + @echo + @echo $(MSG_FLASH) $@ + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +%.eep: %.elf + @echo + @echo $(MSG_EEPROM) $@ + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + +# Create extended listing file from ELF output file. +%.lss: %.elf + @echo + @echo $(MSG_EXTENDED_LISTING) $@ + $(OBJDUMP) -h -S $< > $@ + +# Create a symbol table from ELF output file. +%.sym: %.elf + @echo + @echo $(MSG_SYMBOL_TABLE) $@ + $(NM) -n $< > $@ + + + +# Link: create ELF output file from object files. +.SECONDARY : $(TARGET).elf +.PRECIOUS : $(OBJ) +%.elf: $(OBJ) + @echo + @echo $(MSG_LINKING) $@ + $(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS) + + +# Compile: create object files from C source files. +%.o : %.c + @echo + @echo $(MSG_COMPILING) $< + $(CC) -c $(ALL_CFLAGS) $< -o $@ + + +# Compile: create assembler files from C source files. +%.s : %.c + $(CC) -S $(ALL_CFLAGS) $< -o $@ + + +# Assemble: create object files from assembler source files. +%.o : %.S + @echo + @echo $(MSG_ASSEMBLING) $< + $(CC) -c $(ALL_ASFLAGS) $< -o $@ + +# Create preprocessed source for use in sending a bug report. +%.i : %.c + $(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ + + +# Target: clean project. +clean: begin clean_list end + +clean_list : + @echo + @echo $(MSG_CLEANING) + $(REMOVE) $(TARGET).hex + $(REMOVE) $(TARGET).eep + $(REMOVE) $(TARGET).cof + $(REMOVE) $(TARGET).elf + $(REMOVE) $(TARGET).map + $(REMOVE) $(TARGET).sym + $(REMOVE) $(TARGET).lss + $(REMOVE) $(OBJ) + $(REMOVE) $(LST) + $(REMOVE) $(SRC:.c=.s) + $(REMOVE) $(SRC:.c=.d) + $(REMOVE) .dep/* + + + +# Include the dependency files. +-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) + + +# Listing of phony targets. +.PHONY : all begin finish end sizebefore sizeafter gccversion \ +build elf hex eep lss sym coff extcoff \ +clean clean_list program debug gdb-config + diff --git a/freq-counter/uartlibrary/test_uart.c b/freq-counter/uartlibrary/test_uart.c new file mode 100644 index 0000000..44346b0 --- /dev/null +++ b/freq-counter/uartlibrary/test_uart.c @@ -0,0 +1,130 @@ +/************************************************************************* +Title: example program for the Interrupt controlled UART library +Author: Peter Fleury http://jump.to/fleury +File: $Id: test_uart.c,v 1.4 2005/07/10 11:46:30 Peter Exp $ +Software: AVR-GCC 3.3 +Hardware: any AVR with built-in UART, tested on AT90S8515 at 4 Mhz + +DESCRIPTION: + This example shows how to use the UART library uart.c + +*************************************************************************/ +#include +#include +#include +#include +#include + +#include "uart.h" + + +/* define CPU frequency in Mhz here if not defined in Makefile */ +#ifndef F_CPU +#define F_CPU 4000000UL +#endif + +/* 9600 baud */ +#define UART_BAUD_RATE 9600 + + +int main(void) +{ + unsigned int c; + char buffer[7]; + int num=134; + + + /* + * Initialize UART library, pass baudrate and AVR cpu clock + * with the macro + * UART_BAUD_SELECT() (normal speed mode ) + * or + * UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode) + */ + uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); + + /* + * now enable interrupt, since UART library is interrupt controlled + */ + sei(); + + /* + * Transmit string to UART + * The string is buffered by the uart library in a circular buffer + * and one character at a time is transmitted to the UART using interrupts. + * uart_puts() blocks if it can not write the whole string to the circular + * buffer + */ + uart_puts("String stored in SRAM\n"); + + /* + * Transmit string from program memory to UART + */ + uart_puts_P("String stored in FLASH\n"); + + + /* + * Use standard avr-libc functions to convert numbers into string + * before transmitting via UART + */ + itoa( num, buffer, 10); // convert interger into string (decimal format) + uart_puts(buffer); // and transmit string to UART + + + /* + * Transmit single character to UART + */ + uart_putc('\r'); + + for(;;) + { + /* + * Get received character from ringbuffer + * uart_getc() returns in the lower byte the received character and + * in the higher byte (bitmask) the last receive error + * UART_NO_DATA is returned when no data is available. + * + */ + c = uart_getc(); + if ( c & UART_NO_DATA ) + { + /* + * no data available from UART + */ + } + else + { + /* + * new data available from UART + * check for Frame or Overrun error + */ + if ( c & UART_FRAME_ERROR ) + { + /* Framing Error detected, i.e no stop bit detected */ + uart_puts_P("UART Frame Error: "); + } + if ( c & UART_OVERRUN_ERROR ) + { + /* + * Overrun, a character already present in the UART UDR register was + * not read by the interrupt handler before the next character arrived, + * one or more received characters have been dropped + */ + uart_puts_P("UART Overrun Error: "); + } + if ( c & UART_BUFFER_OVERFLOW ) + { + /* + * We are not reading the receive buffer fast enough, + * one or more received character have been dropped + */ + uart_puts_P("Buffer overflow error: "); + } + /* + * send received character back + */ + uart_putc( (unsigned char)c ); + } + } + +} diff --git a/freq-counter/uartlibrary/uart.c b/freq-counter/uartlibrary/uart.c new file mode 100644 index 0000000..2bc1068 --- /dev/null +++ b/freq-counter/uartlibrary/uart.c @@ -0,0 +1,651 @@ +/************************************************************************* +Title: Interrupt UART library with receive/transmit circular buffers +Author: Peter Fleury http://jump.to/fleury +File: $Id: uart.c,v 1.6.2.1 2007/07/01 11:14:38 peter Exp $ +Software: AVR-GCC 4.1, AVR Libc 1.4.6 or higher +Hardware: any AVR with built-in UART, +License: GNU General Public License + +DESCRIPTION: + An interrupt is generated when the UART has finished transmitting or + receiving a byte. The interrupt handling routines use circular buffers + for buffering received and transmitted data. + + The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define + the buffer size in bytes. Note that these variables must be a + power of 2. + +USAGE: + Refere to the header file uart.h for a description of the routines. + See also example test_uart.c. + +NOTES: + Based on Atmel Application Note AVR306 + +LICENSE: + Copyright (C) 2006 Peter Fleury + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + 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 General Public License for more details. + +*************************************************************************/ +#include +#include +#include +#include "uart.h" + + +/* + * constants and macros + */ + +/* size of RX/TX buffers */ +#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1) +#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1) + +#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK ) +#error RX buffer size is not a power of 2 +#endif +#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK ) +#error TX buffer size is not a power of 2 +#endif + +#if defined(__AVR_AT90S2313__) \ + || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \ + || defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__) \ + || defined(__AVR_ATmega103__) + /* old AVR classic or ATmega103 with one UART */ + #define AT90_UART + #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA + #define UART0_STATUS USR + #define UART0_CONTROL UCR + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE +#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__) + /* old AVR classic with one UART */ + #define AT90_UART + #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE +#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \ + || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \ + || defined(__AVR_ATmega323__) + /* ATmega with one USART */ + #define ATMEGA_USART + #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE +#elif defined(__AVR_ATmega163__) + /* ATmega163 with one UART */ + #define ATMEGA_UART + #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE +#elif defined(__AVR_ATmega162__) + /* ATmega with two USART */ + #define ATMEGA_USART0 + #define ATMEGA_USART1 + #define UART0_RECEIVE_INTERRUPT SIG_USART0_RECV + #define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_USART0_DATA + #define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 + #define UART1_STATUS UCSR1A + #define UART1_CONTROL UCSR1B + #define UART1_DATA UDR1 + #define UART1_UDRIE UDRIE1 +#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) + /* ATmega with two USART */ + #define ATMEGA_USART0 + #define ATMEGA_USART1 + #define UART0_RECEIVE_INTERRUPT SIG_UART0_RECV + #define UART1_RECEIVE_INTERRUPT SIG_UART1_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_UART0_DATA + #define UART1_TRANSMIT_INTERRUPT SIG_UART1_DATA + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 + #define UART1_STATUS UCSR1A + #define UART1_CONTROL UCSR1B + #define UART1_DATA UDR1 + #define UART1_UDRIE UDRIE1 +#elif defined(__AVR_ATmega161__) + /* ATmega with UART */ + #error "AVR ATmega161 currently not supported by this libaray !" +#elif defined(__AVR_ATmega169__) + /* ATmega with one USART */ + #define ATMEGA_USART + #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE +#elif defined(__AVR_ATmega48__) ||defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) + /* ATmega with one USART */ + #define ATMEGA_USART0 + #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 +#elif defined(__AVR_ATtiny2313__) + #define ATMEGA_USART + #define UART0_RECEIVE_INTERRUPT SIG_USART0_RX + #define UART0_TRANSMIT_INTERRUPT SIG_USART0_UDRE + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE +#elif defined(__AVR_ATmega329__) ||defined(__AVR_ATmega3290__) ||\ + defined(__AVR_ATmega649__) ||defined(__AVR_ATmega6490__) ||\ + defined(__AVR_ATmega325__) ||defined(__AVR_ATmega3250__) ||\ + defined(__AVR_ATmega645__) ||defined(__AVR_ATmega6450__) + /* ATmega with one USART */ + #define ATMEGA_USART0 + #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 +#elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega640__) +/* ATmega with two USART */ + #define ATMEGA_USART0 + #define ATMEGA_USART1 + #define UART0_RECEIVE_INTERRUPT SIG_USART0_RECV + #define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_USART0_DATA + #define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 + #define UART1_STATUS UCSR1A + #define UART1_CONTROL UCSR1B + #define UART1_DATA UDR1 + #define UART1_UDRIE UDRIE1 +#elif defined(__AVR_ATmega644__) + /* ATmega with one USART */ + #define ATMEGA_USART0 + #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 +#elif defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__) + /* ATmega with two USART */ + #define ATMEGA_USART0 + #define ATMEGA_USART1 + #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV + #define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV + #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA + #define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 + #define UART1_STATUS UCSR1A + #define UART1_CONTROL UCSR1B + #define UART1_DATA UDR1 + #define UART1_UDRIE UDRIE1 +#else + #error "no UART definition for MCU available" +#endif + + +/* + * module global variables + */ +static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE]; +static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE]; +static volatile unsigned char UART_TxHead; +static volatile unsigned char UART_TxTail; +static volatile unsigned char UART_RxHead; +static volatile unsigned char UART_RxTail; +static volatile unsigned char UART_LastRxError; + +#if defined( ATMEGA_USART1 ) +static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE]; +static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE]; +static volatile unsigned char UART1_TxHead; +static volatile unsigned char UART1_TxTail; +static volatile unsigned char UART1_RxHead; +static volatile unsigned char UART1_RxTail; +static volatile unsigned char UART1_LastRxError; +#endif + + + +SIGNAL(UART0_RECEIVE_INTERRUPT) +/************************************************************************* +Function: UART Receive Complete interrupt +Purpose: called when the UART has received a character +**************************************************************************/ +{ + unsigned char tmphead; + unsigned char data; + unsigned char usr; + unsigned char lastRxError; + + + /* read UART status register and UART data register */ + usr = UART0_STATUS; + data = UART0_DATA; + + /* */ +#if defined( AT90_UART ) + lastRxError = (usr & (_BV(FE)|_BV(DOR)) ); +#elif defined( ATMEGA_USART ) + lastRxError = (usr & (_BV(FE)|_BV(DOR)) ); +#elif defined( ATMEGA_USART0 ) + lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) ); +#elif defined ( ATMEGA_UART ) + lastRxError = (usr & (_BV(FE)|_BV(DOR)) ); +#endif + + /* calculate buffer index */ + tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK; + + if ( tmphead == UART_RxTail ) { + /* error: receive buffer overflow */ + lastRxError = UART_BUFFER_OVERFLOW >> 8; + }else{ + /* store new index */ + UART_RxHead = tmphead; + /* store received data in buffer */ + UART_RxBuf[tmphead] = data; + } + UART_LastRxError = lastRxError; +} + + +SIGNAL(UART0_TRANSMIT_INTERRUPT) +/************************************************************************* +Function: UART Data Register Empty interrupt +Purpose: called when the UART is ready to transmit the next byte +**************************************************************************/ +{ + unsigned char tmptail; + + + if ( UART_TxHead != UART_TxTail) { + /* calculate and store new buffer index */ + tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK; + UART_TxTail = tmptail; + /* get one byte from buffer and write it to UART */ + UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */ + }else{ + /* tx buffer empty, disable UDRE interrupt */ + UART0_CONTROL &= ~_BV(UART0_UDRIE); + } +} + + +/************************************************************************* +Function: uart_init() +Purpose: initialize UART and set baudrate +Input: baudrate using macro UART_BAUD_SELECT() +Returns: none +**************************************************************************/ +void uart_init(unsigned int baudrate) +{ + UART_TxHead = 0; + UART_TxTail = 0; + UART_RxHead = 0; + UART_RxTail = 0; + +#if defined( AT90_UART ) + /* set baud rate */ + UBRR = (unsigned char)baudrate; + + /* enable UART receiver and transmmitter and receive complete interrupt */ + UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN); + +#elif defined (ATMEGA_USART) + /* Set baud rate */ + if ( baudrate & 0x8000 ) + { + UART0_STATUS = (1<>8); + UBRRL = (unsigned char) baudrate; + + /* Enable USART receiver and transmitter and receive complete interrupt */ + UART0_CONTROL = _BV(RXCIE)|(1<>8); + UBRR0L = (unsigned char) baudrate; + + /* Enable USART receiver and transmitter and receive complete interrupt */ + UART0_CONTROL = _BV(RXCIE0)|(1<>8); + UBRR = (unsigned char) baudrate; + + /* Enable UART receiver and transmitter and receive complete interrupt */ + UART0_CONTROL = _BV(RXCIE)|(1<> 8; + }else{ + /* store new index */ + UART1_RxHead = tmphead; + /* store received data in buffer */ + UART1_RxBuf[tmphead] = data; + } + UART1_LastRxError = lastRxError; +} + + +SIGNAL(UART1_TRANSMIT_INTERRUPT) +/************************************************************************* +Function: UART1 Data Register Empty interrupt +Purpose: called when the UART1 is ready to transmit the next byte +**************************************************************************/ +{ + unsigned char tmptail; + + + if ( UART1_TxHead != UART1_TxTail) { + /* calculate and store new buffer index */ + tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK; + UART1_TxTail = tmptail; + /* get one byte from buffer and write it to UART */ + UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */ + }else{ + /* tx buffer empty, disable UDRE interrupt */ + UART1_CONTROL &= ~_BV(UART1_UDRIE); + } +} + + +/************************************************************************* +Function: uart1_init() +Purpose: initialize UART1 and set baudrate +Input: baudrate using macro UART_BAUD_SELECT() +Returns: none +**************************************************************************/ +void uart1_init(unsigned int baudrate) +{ + UART1_TxHead = 0; + UART1_TxTail = 0; + UART1_RxHead = 0; + UART1_RxTail = 0; + + + /* Set baud rate */ + if ( baudrate & 0x8000 ) + { + UART1_STATUS = (1<>8); + UBRR1L = (unsigned char) baudrate; + + /* Enable USART receiver and transmitter and receive complete interrupt */ + UART1_CONTROL = _BV(RXCIE1)|(1< http://jump.to/fleury +File: $Id: uart.h,v 1.8.2.1 2007/07/01 11:14:38 peter Exp $ +Software: AVR-GCC 4.1, AVR Libc 1.4 +Hardware: any AVR with built-in UART, tested on AT90S8515 & ATmega8 at 4 Mhz +License: GNU General Public License +Usage: see Doxygen manual + +LICENSE: + Copyright (C) 2006 Peter Fleury + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + 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 General Public License for more details. + +************************************************************************/ + +/** + * @defgroup pfleury_uart UART Library + * @code #include @endcode + * + * @brief Interrupt UART library using the built-in UART with transmit and receive circular buffers. + * + * This library can be used to transmit and receive data through the built in UART. + * + * An interrupt is generated when the UART has finished transmitting or + * receiving a byte. The interrupt handling routines use circular buffers + * for buffering received and transmitted data. + * + * The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define + * the size of the circular buffers in bytes. Note that these constants must be a power of 2. + * You may need to adapt this constants to your target and your application by adding + * CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_RX_BUFFER_SIZE=nn to your Makefile. + * + * @note Based on Atmel Application Note AVR306 + * @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury + */ + +/**@{*/ + + +#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 +#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !" +#endif + + +/* +** constants and macros +*/ + +/** @brief UART Baudrate Expression + * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz + * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 + */ +#define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1) + +/** @brief UART Baudrate Expression for ATmega double speed mode + * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz + * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 + */ +#define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) (((xtalCpu)/((baudRate)*8l)-1)|0x8000) + + +/** Size of the circular receive buffer, must be power of 2 */ +#ifndef UART_RX_BUFFER_SIZE +#define UART_RX_BUFFER_SIZE 32 +#endif +/** Size of the circular transmit buffer, must be power of 2 */ +#ifndef UART_TX_BUFFER_SIZE +#define UART_TX_BUFFER_SIZE 32 +#endif + +/* test if the size of the circular buffers fits into SRAM */ +#if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) ) +#error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM" +#endif + +/* +** high byte error return code of uart_getc() +*/ +#define UART_FRAME_ERROR 0x0800 /* Framing Error by UART */ +#define UART_OVERRUN_ERROR 0x0400 /* Overrun condition by UART */ +#define UART_BUFFER_OVERFLOW 0x0200 /* receive ringbuffer overflow */ +#define UART_NO_DATA 0x0100 /* no receive data available */ + + +/* +** function prototypes +*/ + +/** + @brief Initialize UART and set baudrate + @param baudrate Specify baudrate using macro UART_BAUD_SELECT() + @return none +*/ +extern void uart_init(unsigned int baudrate); + + +/** + * @brief Get received byte from ringbuffer + * + * Returns in the lower byte the received character and in the + * higher byte the last receive error. + * UART_NO_DATA is returned when no data is available. + * + * @param void + * @return lower byte: received byte from ringbuffer + * @return higher byte: last receive status + * - \b 0 successfully received data from UART + * - \b UART_NO_DATA + *
no receive data available + * - \b UART_BUFFER_OVERFLOW + *
Receive ringbuffer overflow. + * We are not reading the receive buffer fast enough, + * one or more received character have been dropped + * - \b UART_OVERRUN_ERROR + *
Overrun condition by UART. + * A character already present in the UART UDR register was + * not read by the interrupt handler before the next character arrived, + * one or more received characters have been dropped. + * - \b UART_FRAME_ERROR + *
Framing Error by UART + */ +extern unsigned int uart_getc(void); + + +/** + * @brief Put byte to ringbuffer for transmitting via UART + * @param data byte to be transmitted + * @return none + */ +extern void uart_putc(unsigned char data); + + +/** + * @brief Put string to ringbuffer for transmitting via UART + * + * The string is buffered by the uart library in a circular buffer + * and one character at a time is transmitted to the UART using interrupts. + * Blocks if it can not write the whole string into the circular buffer. + * + * @param s string to be transmitted + * @return none + */ +extern void uart_puts(const char *s ); + + +/** + * @brief Put string from program memory to ringbuffer for transmitting via UART. + * + * The string is buffered by the uart library in a circular buffer + * and one character at a time is transmitted to the UART using interrupts. + * Blocks if it can not write the whole string into the circular buffer. + * + * @param s program memory string to be transmitted + * @return none + * @see uart_puts_P + */ +extern void uart_puts_p(const char *s ); + +/** + * @brief Macro to automatically put a string constant into program memory + */ +#define uart_puts_P(__s) uart_puts_p(PSTR(__s)) + + + +/** @brief Initialize USART1 (only available on selected ATmegas) @see uart_init */ +extern void uart1_init(unsigned int baudrate); +/** @brief Get received byte of USART1 from ringbuffer. (only available on selected ATmega) @see uart_getc */ +extern unsigned int uart1_getc(void); +/** @brief Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_putc */ +extern void uart1_putc(unsigned char data); +/** @brief Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts */ +extern void uart1_puts(const char *s ); +/** @brief Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts_p */ +extern void uart1_puts_p(const char *s ); +/** @brief Macro to automatically put a string constant into program memory */ +#define uart1_puts_P(__s) uart1_puts_p(PSTR(__s)) + +/**@}*/ + + +#endif // UART_H +