setting up new branch 2
This commit is contained in:
parent
994fa1b4c7
commit
595b66a341
|
|
@ -1,75 +0,0 @@
|
||||||
##############################################################################
|
|
||||||
# #
|
|
||||||
# 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 $< $@
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
#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;);
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
#ifndef _ADC_H
|
|
||||||
#define _ADC_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,595 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
Title : HD44780U LCD library
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <inttypes.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#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 <us> 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 */
|
|
||||||
|
|
@ -1,263 +0,0 @@
|
||||||
#ifndef LCD_H
|
|
||||||
#define LCD_H
|
|
||||||
/*************************************************************************
|
|
||||||
Title : C include file for the HD44780U LCD library (lcd.c)
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <lcd.h> @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 <a href="http://homepage.sunrise.ch/mysunrise/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780 Based LCD to an AVR</a>
|
|
||||||
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 <inttypes.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Initialize display and select type of cursor
|
|
||||||
@param dispAttr \b LCD_DISP_OFF display off\n
|
|
||||||
\b LCD_DISP_ON display on, cursor off\n
|
|
||||||
\b LCD_DISP_ON_CURSOR display on, cursor on\n
|
|
||||||
\b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_init(uint8_t dispAttr);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Clear display and set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_clrscr(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_home(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to specified position
|
|
||||||
|
|
||||||
@param x horizontal position\n (0: left most position)
|
|
||||||
@param y vertical position\n (0: first line)
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_gotoxy(uint8_t x, uint8_t y);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display character at current cursor position
|
|
||||||
@param c character to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_putc(char c);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string without auto linefeed
|
|
||||||
@param s string to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_puts(const char *s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string from program memory without auto linefeed
|
|
||||||
@param s string from program memory be be displayed
|
|
||||||
@return none
|
|
||||||
@see lcd_puts_P
|
|
||||||
*/
|
|
||||||
void lcd_puts_p(const char *progmem_s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send LCD controller instruction command
|
|
||||||
@param cmd instruction to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_command(uint8_t cmd);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send data byte to LCD controller
|
|
||||||
|
|
||||||
Similar to lcd_putc(), but without interpreting LF
|
|
||||||
@param data byte to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_data(uint8_t data);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief macros for automatically storing string constant in program memory
|
|
||||||
*/
|
|
||||||
#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))
|
|
||||||
|
|
||||||
/*@}*/
|
|
||||||
#endif //LCD_H
|
|
||||||
|
|
@ -1,282 +0,0 @@
|
||||||
8870 execve("/usr/bin/avr-gcc", ["avr-gcc", "-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) = 0x9a43000
|
|
||||||
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) = 0xb7ed7000
|
|
||||||
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) = 0xb7ed6000
|
|
||||||
8870 mmap2(NULL, 1308240, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7d96000
|
|
||||||
8870 mmap2(0xb7ed0000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x13a) = 0xb7ed0000
|
|
||||||
8870 mmap2(0xb7ed3000, 9808, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7ed3000
|
|
||||||
8870 close(3) = 0
|
|
||||||
8870 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7d95000
|
|
||||||
8870 set_thread_area({entry_number:-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) = ?
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef _RINGBUFFER_H
|
|
||||||
#define _RINGBUFFER_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#ifndef _SERIAL_H
|
|
||||||
#define _SERIAL_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
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 $< $@
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#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++;
|
|
||||||
}
|
|
||||||
|
|
@ -1,595 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
Title : HD44780U LCD library
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <inttypes.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#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 <us> 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 */
|
|
||||||
|
|
@ -1,263 +0,0 @@
|
||||||
#ifndef LCD_H
|
|
||||||
#define LCD_H
|
|
||||||
/*************************************************************************
|
|
||||||
Title : C include file for the HD44780U LCD library (lcd.c)
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <lcd.h> @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 <a href="http://homepage.sunrise.ch/mysunrise/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780 Based LCD to an AVR</a>
|
|
||||||
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 <inttypes.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Initialize display and select type of cursor
|
|
||||||
@param dispAttr \b LCD_DISP_OFF display off\n
|
|
||||||
\b LCD_DISP_ON display on, cursor off\n
|
|
||||||
\b LCD_DISP_ON_CURSOR display on, cursor on\n
|
|
||||||
\b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_init(uint8_t dispAttr);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Clear display and set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_clrscr(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_home(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to specified position
|
|
||||||
|
|
||||||
@param x horizontal position\n (0: left most position)
|
|
||||||
@param y vertical position\n (0: first line)
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_gotoxy(uint8_t x, uint8_t y);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display character at current cursor position
|
|
||||||
@param c character to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_putc(char c);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string without auto linefeed
|
|
||||||
@param s string to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_puts(const char *s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string from program memory without auto linefeed
|
|
||||||
@param s string from program memory be be displayed
|
|
||||||
@return none
|
|
||||||
@see lcd_puts_P
|
|
||||||
*/
|
|
||||||
void lcd_puts_p(const char *progmem_s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send LCD controller instruction command
|
|
||||||
@param cmd instruction to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_command(uint8_t cmd);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send data byte to LCD controller
|
|
||||||
|
|
||||||
Similar to lcd_putc(), but without interpreting LF
|
|
||||||
@param data byte to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_data(uint8_t data);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief macros for automatically storing string constant in program memory
|
|
||||||
*/
|
|
||||||
#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))
|
|
||||||
|
|
||||||
/*@}*/
|
|
||||||
#endif //LCD_H
|
|
||||||
Binary file not shown.
|
|
@ -1,49 +0,0 @@
|
||||||
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 }
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB |
File diff suppressed because it is too large
Load Diff
|
|
@ -1,609 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
Title : HD44780U LCD library
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <inttypes.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#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 <us> 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_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)
|
|
||||||
&& (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)
|
|
||||||
&& (LCD_RS_PIN == 4 ) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6 ) )
|
|
||||||
{
|
|
||||||
/* configure all port bits as output (all LCD lines on same port) */
|
|
||||||
DDR(LCD_DATA0_PORT) |= 0x7F;
|
|
||||||
}
|
|
||||||
else 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 all port bits as output (all LCD data lines on same port, but control lines on different ports) */
|
|
||||||
DDR(LCD_DATA0_PORT) |= 0x0F;
|
|
||||||
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 */
|
|
||||||
|
|
@ -1,265 +0,0 @@
|
||||||
#ifndef LCD_H
|
|
||||||
#define LCD_H
|
|
||||||
/*************************************************************************
|
|
||||||
Title : C include file for the HD44780U LCD library (lcd.c)
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <lcd.h> @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 <a href="http://homepage.sunrise.ch/mysunrise/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780 Based LCD to an AVR</a>
|
|
||||||
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 <inttypes.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Initialize display and select type of cursor
|
|
||||||
@param dispAttr \b LCD_DISP_OFF display off\n
|
|
||||||
\b LCD_DISP_ON display on, cursor off\n
|
|
||||||
\b LCD_DISP_ON_CURSOR display on, cursor on\n
|
|
||||||
\b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
extern void lcd_init(uint8_t dispAttr);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Clear display and set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
extern void lcd_clrscr(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
extern void lcd_home(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to specified position
|
|
||||||
|
|
||||||
@param x horizontal position\n (0: left most position)
|
|
||||||
@param y vertical position\n (0: first line)
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
extern void lcd_gotoxy(uint8_t x, uint8_t y);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display character at current cursor position
|
|
||||||
@param c character to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
extern void lcd_putc(char c);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string without auto linefeed
|
|
||||||
@param s string to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
extern void lcd_puts(const char *s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string from program memory without auto linefeed
|
|
||||||
@param s string from program memory be be displayed
|
|
||||||
@return none
|
|
||||||
@see lcd_puts_P
|
|
||||||
*/
|
|
||||||
extern void lcd_puts_p(const char *progmem_s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send LCD controller instruction command
|
|
||||||
@param cmd instruction to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
extern void lcd_command(uint8_t cmd);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send data byte to LCD controller
|
|
||||||
|
|
||||||
Similar to lcd_putc(), but without interpreting LF
|
|
||||||
@param data byte to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
extern void lcd_data(uint8_t data);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief macros for automatically storing string constant in program memory
|
|
||||||
*/
|
|
||||||
#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))
|
|
||||||
|
|
||||||
/*@}*/
|
|
||||||
#endif //LCD_H
|
|
||||||
|
|
@ -1,425 +0,0 @@
|
||||||
# Hey Emacs, this is a -*- makefile -*-
|
|
||||||
#
|
|
||||||
# WinAVR Sample makefile written by Eric B. Weddington, Jörg Wunsch, et al.
|
|
||||||
# Released to the Public Domain
|
|
||||||
# Please read the make user manual!
|
|
||||||
#
|
|
||||||
# Additional material for this makefile was submitted by:
|
|
||||||
# Tim Henigan
|
|
||||||
# Peter Fleury
|
|
||||||
# Reiner Patommel
|
|
||||||
# Sander Pool
|
|
||||||
# Frederik Rouleau
|
|
||||||
# Markus Pfaff
|
|
||||||
#
|
|
||||||
# On command line:
|
|
||||||
#
|
|
||||||
# make all = Make software.
|
|
||||||
#
|
|
||||||
# make clean = Clean out built project files.
|
|
||||||
#
|
|
||||||
# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
|
|
||||||
#
|
|
||||||
# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
|
|
||||||
# 4.07 or greater).
|
|
||||||
#
|
|
||||||
# make program = Download the hex file to the device, using avrdude. Please
|
|
||||||
# customize the avrdude settings below first!
|
|
||||||
#
|
|
||||||
# make filename.s = Just compile filename.c into the assembler code only
|
|
||||||
#
|
|
||||||
# To rebuild project do "make clean" then "make all".
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
# MCU name
|
|
||||||
MCU = at90s8515
|
|
||||||
|
|
||||||
# Output format. (can be srec, ihex, binary)
|
|
||||||
FORMAT = ihex
|
|
||||||
|
|
||||||
# Target file name (without extension).
|
|
||||||
TARGET = test_lcd
|
|
||||||
|
|
||||||
|
|
||||||
# List C source files here. (C dependencies are automatically generated.)
|
|
||||||
SRC = $(TARGET).c lcd.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 stabs [default], or dwarf-2.
|
|
||||||
# AVR (extended) COFF 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.
|
|
||||||
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 =
|
|
||||||
|
|
||||||
# Place -I options here
|
|
||||||
CINCS =
|
|
||||||
|
|
||||||
|
|
||||||
# Compiler flags.
|
|
||||||
# -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 flags.
|
|
||||||
# -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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#Additional libraries.
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
PRINTF_LIB =
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
SCANF_LIB =
|
|
||||||
|
|
||||||
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 flags.
|
|
||||||
# -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 support using avrdude. Settings and variables.
|
|
||||||
|
|
||||||
# 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 <http://savannah.nongnu.org/projects/avrdude>
|
|
||||||
# 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
|
|
||||||
|
|
||||||
|
|
@ -1,167 +0,0 @@
|
||||||
/*************************************************************************
|
|
||||||
Title: testing output to a HD44780 based LCD display.
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <stdlib.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#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();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef _RINGBUFFER_H
|
|
||||||
#define _RINGBUFFER_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#ifndef _SERIAL_H
|
|
||||||
#define _SERIAL_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
Binary file not shown.
|
|
@ -1,49 +0,0 @@
|
||||||
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 }
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB |
|
|
@ -1,560 +0,0 @@
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
||||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
|
|
||||||
<title>AVR-GCC libraries: UART Library</title>
|
|
||||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
|
||||||
</head><body>
|
|
||||||
<!-- Generated by Doxygen 1.4.1 -->
|
|
||||||
<h1>UART Library</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
|
|
||||||
Interrupt UART library using the built-in UART with transmit and receive circular buffers.
|
|
||||||
<p>
|
|
||||||
<div class="fragment"><pre class="fragment"><span class="preprocessor"> #include <uart.h></span>
|
|
||||||
</pre></div><p>
|
|
||||||
This library can be used to transmit and receive data through the built in UART.<p>
|
|
||||||
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.<p>
|
|
||||||
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.<p>
|
|
||||||
<dl compact><dt><b>Note:</b></dt><dd>Based on Atmel Application Note AVR306 </dd></dl>
|
|
||||||
<dl compact><dt><b>Author:</b></dt><dd>Peter Fleury <a href="mailto:pfleury@gmx.ch">pfleury@gmx.ch</a> <a href="http://jump.to/fleury">http://jump.to/fleury</a> </dd></dl>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<table border="0" cellpadding="0" cellspacing="0">
|
|
||||||
<tr><td></td></tr>
|
|
||||||
<tr><td colspan="2"><br><h2>Defines</h2></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga10">UART_BAUD_SELECT</a>(baudRate, xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">UART Baudrate Expression. <a href="#ga10"></a><br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga11">UART_BAUD_SELECT_DOUBLE_SPEED</a>(baudRate, xtalCpu) (((xtalCpu)/((baudRate)*8l)-1)|0x8000)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">UART Baudrate Expression for ATmega double speed mode. <a href="#ga11"></a><br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga12">UART_RX_BUFFER_SIZE</a> 32</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga13">UART_TX_BUFFER_SIZE</a> 32</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga14" doxytag="pfleury_uart::UART_FRAME_ERROR"></a>
|
|
||||||
#define </td><td class="memItemRight" valign="bottom"><b>UART_FRAME_ERROR</b> 0x0800</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga15" doxytag="pfleury_uart::UART_OVERRUN_ERROR"></a>
|
|
||||||
#define </td><td class="memItemRight" valign="bottom"><b>UART_OVERRUN_ERROR</b> 0x0400</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga16" doxytag="pfleury_uart::UART_BUFFER_OVERFLOW"></a>
|
|
||||||
#define </td><td class="memItemRight" valign="bottom"><b>UART_BUFFER_OVERFLOW</b> 0x0200</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga17" doxytag="pfleury_uart::UART_NO_DATA"></a>
|
|
||||||
#define </td><td class="memItemRight" valign="bottom"><b>UART_NO_DATA</b> 0x0100</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga18" doxytag="pfleury_uart::uart_puts_P"></a>
|
|
||||||
#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga18">uart_puts_P</a>(__s) uart_puts_p(PSTR(__s))</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Macro to automatically put a string constant into program memory. <br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga19" doxytag="pfleury_uart::uart1_puts_P"></a>
|
|
||||||
#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga19">uart1_puts_P</a>(__s) uart1_puts_p(PSTR(__s))</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Macro to automatically put a string constant into program memory. <br></td></tr>
|
|
||||||
<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga0">uart_init</a> (unsigned int baudrate)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Initialize UART and set baudrate. <a href="#ga0"></a><br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">unsigned int </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga1">uart_getc</a> (void)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Get received byte from ringbuffer. <a href="#ga1"></a><br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga2">uart_putc</a> (unsigned char data)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Put byte to ringbuffer for transmitting via UART. <a href="#ga2"></a><br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga3">uart_puts</a> (const char *s)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Put string to ringbuffer for transmitting via UART. <a href="#ga3"></a><br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga4">uart_puts_p</a> (const char *s)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Put string from program memory to ringbuffer for transmitting via UART. <a href="#ga4"></a><br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga5">uart1_init</a> (unsigned int baudrate)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Initialize USART1 (only available on selected ATmegas). <a href="#ga5"></a><br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">unsigned int </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga6">uart1_getc</a> (void)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Get received byte of USART1 from ringbuffer. (only available on selected ATmega). <a href="#ga6"></a><br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga7">uart1_putc</a> (unsigned char data)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega). <a href="#ga7"></a><br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga8">uart1_puts</a> (const char *s)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega). <a href="#ga8"></a><br></td></tr>
|
|
||||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga9">uart1_puts_p</a> (const char *s)</td></tr>
|
|
||||||
|
|
||||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega). <a href="#ga9"></a><br></td></tr>
|
|
||||||
</table>
|
|
||||||
<hr><h2>Define Documentation</h2>
|
|
||||||
<a class="anchor" name="ga10" doxytag="uart.h::UART_BAUD_SELECT"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">#define UART_BAUD_SELECT </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">baudRate, <tr>
|
|
||||||
<td class="md" nowrap align="right"></td>
|
|
||||||
<td class="md"></td>
|
|
||||||
<td class="md" nowrap>xtalCpu </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap> ((xtalCpu)/((baudRate)*16l)-1)</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
UART Baudrate Expression.
|
|
||||||
<p>
|
|
||||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
|
||||||
<table border="0" cellspacing="2" cellpadding="0">
|
|
||||||
<tr><td valign="top"></td><td valign="top"><em>xtalcpu</em> </td><td>system clock in Mhz, e.g. 4000000L for 4Mhz </td></tr>
|
|
||||||
<tr><td valign="top"></td><td valign="top"><em>baudrate</em> </td><td>baudrate in bps, e.g. 1200, 2400, 9600 </td></tr>
|
|
||||||
</table>
|
|
||||||
</dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga11" doxytag="uart.h::UART_BAUD_SELECT_DOUBLE_SPEED"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">#define UART_BAUD_SELECT_DOUBLE_SPEED </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">baudRate, <tr>
|
|
||||||
<td class="md" nowrap align="right"></td>
|
|
||||||
<td class="md"></td>
|
|
||||||
<td class="md" nowrap>xtalCpu </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap> (((xtalCpu)/((baudRate)*8l)-1)|0x8000)</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
UART Baudrate Expression for ATmega double speed mode.
|
|
||||||
<p>
|
|
||||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
|
||||||
<table border="0" cellspacing="2" cellpadding="0">
|
|
||||||
<tr><td valign="top"></td><td valign="top"><em>xtalcpu</em> </td><td>system clock in Mhz, e.g. 4000000L for 4Mhz </td></tr>
|
|
||||||
<tr><td valign="top"></td><td valign="top"><em>baudrate</em> </td><td>baudrate in bps, e.g. 1200, 2400, 9600 </td></tr>
|
|
||||||
</table>
|
|
||||||
</dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga12" doxytag="uart.h::UART_RX_BUFFER_SIZE"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">#define UART_RX_BUFFER_SIZE 32 </td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Size of the circular receive buffer, must be power of 2 </td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga13" doxytag="uart.h::UART_TX_BUFFER_SIZE"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">#define UART_TX_BUFFER_SIZE 32 </td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Size of the circular transmit buffer, must be power of 2 </td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr><h2>Function Documentation</h2>
|
|
||||||
<a class="anchor" name="ga0" doxytag="uart.h::uart_init"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">void uart_init </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">unsigned int </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> <em>baudrate</em> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Initialize UART and set baudrate.
|
|
||||||
<p>
|
|
||||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
|
||||||
<table border="0" cellspacing="2" cellpadding="0">
|
|
||||||
<tr><td valign="top"></td><td valign="top"><em>baudrate</em> </td><td>Specify baudrate using macro <a class="el" href="group__pfleury__uart.html#ga10">UART_BAUD_SELECT()</a> </td></tr>
|
|
||||||
</table>
|
|
||||||
</dl>
|
|
||||||
<dl compact><dt><b>Returns:</b></dt><dd>none </dd></dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga1" doxytag="uart.h::uart_getc"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">unsigned int uart_getc </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">void </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Get received byte from ringbuffer.
|
|
||||||
<p>
|
|
||||||
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.<p>
|
|
||||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
|
||||||
<table border="0" cellspacing="2" cellpadding="0">
|
|
||||||
<tr><td valign="top"></td><td valign="top"><em>void</em> </td><td></td></tr>
|
|
||||||
</table>
|
|
||||||
</dl>
|
|
||||||
<dl compact><dt><b>Returns:</b></dt><dd>lower byte: received byte from ringbuffer <p>
|
|
||||||
higher byte: last receive status<ul>
|
|
||||||
<li><b>0</b> successfully received data from UART</li><li><b>UART_NO_DATA</b> <br>
|
|
||||||
no receive data available</li><li><b>UART_BUFFER_OVERFLOW</b> <br>
|
|
||||||
Receive ringbuffer overflow. We are not reading the receive buffer fast enough, one or more received character have been dropped</li><li><b>UART_OVERRUN_ERROR</b> <br>
|
|
||||||
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.</li><li><b>UART_FRAME_ERROR</b> <br>
|
|
||||||
Framing Error by UART </li></ul>
|
|
||||||
</dd></dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga2" doxytag="uart.h::uart_putc"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">void uart_putc </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">unsigned char </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> <em>data</em> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Put byte to ringbuffer for transmitting via UART.
|
|
||||||
<p>
|
|
||||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
|
||||||
<table border="0" cellspacing="2" cellpadding="0">
|
|
||||||
<tr><td valign="top"></td><td valign="top"><em>data</em> </td><td>byte to be transmitted </td></tr>
|
|
||||||
</table>
|
|
||||||
</dl>
|
|
||||||
<dl compact><dt><b>Returns:</b></dt><dd>none </dd></dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga3" doxytag="uart.h::uart_puts"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">void uart_puts </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">const char * </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> <em>s</em> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Put string to ringbuffer for transmitting via UART.
|
|
||||||
<p>
|
|
||||||
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.<p>
|
|
||||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
|
||||||
<table border="0" cellspacing="2" cellpadding="0">
|
|
||||||
<tr><td valign="top"></td><td valign="top"><em>s</em> </td><td>string to be transmitted </td></tr>
|
|
||||||
</table>
|
|
||||||
</dl>
|
|
||||||
<dl compact><dt><b>Returns:</b></dt><dd>none </dd></dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga4" doxytag="uart.h::uart_puts_p"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">void uart_puts_p </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">const char * </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> <em>s</em> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Put string from program memory to ringbuffer for transmitting via UART.
|
|
||||||
<p>
|
|
||||||
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.<p>
|
|
||||||
<dl compact><dt><b>Parameters:</b></dt><dd>
|
|
||||||
<table border="0" cellspacing="2" cellpadding="0">
|
|
||||||
<tr><td valign="top"></td><td valign="top"><em>s</em> </td><td>program memory string to be transmitted </td></tr>
|
|
||||||
</table>
|
|
||||||
</dl>
|
|
||||||
<dl compact><dt><b>Returns:</b></dt><dd>none </dd></dl>
|
|
||||||
<dl compact><dt><b>See also:</b></dt><dd><a class="el" href="group__pfleury__uart.html#ga18">uart_puts_P</a> </dd></dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga5" doxytag="uart.h::uart1_init"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">void uart1_init </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">unsigned int </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> <em>baudrate</em> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Initialize USART1 (only available on selected ATmegas).
|
|
||||||
<p>
|
|
||||||
<dl compact><dt><b>See also:</b></dt><dd><a class="el" href="group__pfleury__uart.html#ga0">uart_init</a> </dd></dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga6" doxytag="uart.h::uart1_getc"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">unsigned int uart1_getc </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">void </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Get received byte of USART1 from ringbuffer. (only available on selected ATmega).
|
|
||||||
<p>
|
|
||||||
<dl compact><dt><b>See also:</b></dt><dd><a class="el" href="group__pfleury__uart.html#ga1">uart_getc</a> </dd></dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga7" doxytag="uart.h::uart1_putc"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">void uart1_putc </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">unsigned char </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> <em>data</em> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega).
|
|
||||||
<p>
|
|
||||||
<dl compact><dt><b>See also:</b></dt><dd><a class="el" href="group__pfleury__uart.html#ga2">uart_putc</a> </dd></dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga8" doxytag="uart.h::uart1_puts"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">void uart1_puts </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">const char * </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> <em>s</em> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega).
|
|
||||||
<p>
|
|
||||||
<dl compact><dt><b>See also:</b></dt><dd><a class="el" href="group__pfleury__uart.html#ga3">uart_puts</a> </dd></dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a class="anchor" name="ga9" doxytag="uart.h::uart1_puts_p"></a><p>
|
|
||||||
<table class="mdTable" cellpadding="2" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td class="mdRow">
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td class="md" nowrap valign="top">void uart1_puts_p </td>
|
|
||||||
<td class="md" valign="top">( </td>
|
|
||||||
<td class="md" nowrap valign="top">const char * </td>
|
|
||||||
<td class="mdname1" valign="top" nowrap> <em>s</em> </td>
|
|
||||||
<td class="md" valign="top"> ) </td>
|
|
||||||
<td class="md" nowrap></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table cellspacing="5" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega).
|
|
||||||
<p>
|
|
||||||
<dl compact><dt><b>See also:</b></dt><dd><a class="el" href="group__pfleury__uart.html#ga4">uart_puts_p</a> </dd></dl>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr size="1"><address style="align: right;"><small>Generated on Sun Jul 10 13:47:45 2005 for AVR-GCC libraries by
|
|
||||||
<a href="http://www.doxygen.org/index.html">
|
|
||||||
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.4.1 </small></address>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,508 +0,0 @@
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# 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 <http://savannah.nongnu.org/projects/avrdude>
|
|
||||||
# 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
|
|
||||||
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
/*************************************************************************
|
|
||||||
Title: example program for the Interrupt controlled UART library
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <stdlib.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
||||||
#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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,651 +0,0 @@
|
||||||
/*************************************************************************
|
|
||||||
Title: Interrupt UART library with receive/transmit circular buffers
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#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<<U2X); //Enable 2x speed
|
|
||||||
baudrate &= ~0x8000;
|
|
||||||
}
|
|
||||||
UBRRH = (unsigned char)(baudrate>>8);
|
|
||||||
UBRRL = (unsigned char) baudrate;
|
|
||||||
|
|
||||||
/* Enable USART receiver and transmitter and receive complete interrupt */
|
|
||||||
UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
|
|
||||||
|
|
||||||
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
|
||||||
#ifdef URSEL
|
|
||||||
UCSRC = (1<<URSEL)|(3<<UCSZ0);
|
|
||||||
#else
|
|
||||||
UCSRC = (3<<UCSZ0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined (ATMEGA_USART0 )
|
|
||||||
/* Set baud rate */
|
|
||||||
if ( baudrate & 0x8000 )
|
|
||||||
{
|
|
||||||
UART0_STATUS = (1<<U2X0); //Enable 2x speed
|
|
||||||
baudrate &= ~0x8000;
|
|
||||||
}
|
|
||||||
UBRR0H = (unsigned char)(baudrate>>8);
|
|
||||||
UBRR0L = (unsigned char) baudrate;
|
|
||||||
|
|
||||||
/* Enable USART receiver and transmitter and receive complete interrupt */
|
|
||||||
UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
|
|
||||||
|
|
||||||
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
|
||||||
#ifdef URSEL0
|
|
||||||
UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
|
|
||||||
#else
|
|
||||||
UCSR0C = (3<<UCSZ00);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined ( ATMEGA_UART )
|
|
||||||
/* set baud rate */
|
|
||||||
if ( baudrate & 0x8000 )
|
|
||||||
{
|
|
||||||
UART0_STATUS = (1<<U2X); //Enable 2x speed
|
|
||||||
baudrate &= ~0x8000;
|
|
||||||
}
|
|
||||||
UBRRHI = (unsigned char)(baudrate>>8);
|
|
||||||
UBRR = (unsigned char) baudrate;
|
|
||||||
|
|
||||||
/* Enable UART receiver and transmitter and receive complete interrupt */
|
|
||||||
UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}/* uart_init */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
Function: uart_getc()
|
|
||||||
Purpose: return byte from ringbuffer
|
|
||||||
Returns: lower byte: received byte from ringbuffer
|
|
||||||
higher byte: last receive error
|
|
||||||
**************************************************************************/
|
|
||||||
unsigned int uart_getc(void)
|
|
||||||
{
|
|
||||||
unsigned char tmptail;
|
|
||||||
unsigned char data;
|
|
||||||
|
|
||||||
|
|
||||||
if ( UART_RxHead == UART_RxTail ) {
|
|
||||||
return UART_NO_DATA; /* no data available */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calculate /store buffer index */
|
|
||||||
tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
|
|
||||||
UART_RxTail = tmptail;
|
|
||||||
|
|
||||||
/* get data from receive buffer */
|
|
||||||
data = UART_RxBuf[tmptail];
|
|
||||||
|
|
||||||
return (UART_LastRxError << 8) + data;
|
|
||||||
|
|
||||||
}/* uart_getc */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
Function: uart_putc()
|
|
||||||
Purpose: write byte to ringbuffer for transmitting via UART
|
|
||||||
Input: byte to be transmitted
|
|
||||||
Returns: none
|
|
||||||
**************************************************************************/
|
|
||||||
void uart_putc(unsigned char data)
|
|
||||||
{
|
|
||||||
unsigned char tmphead;
|
|
||||||
|
|
||||||
|
|
||||||
tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
|
|
||||||
|
|
||||||
while ( tmphead == UART_TxTail ){
|
|
||||||
;/* wait for free space in buffer */
|
|
||||||
}
|
|
||||||
|
|
||||||
UART_TxBuf[tmphead] = data;
|
|
||||||
UART_TxHead = tmphead;
|
|
||||||
|
|
||||||
/* enable UDRE interrupt */
|
|
||||||
UART0_CONTROL |= _BV(UART0_UDRIE);
|
|
||||||
|
|
||||||
}/* uart_putc */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
Function: uart_puts()
|
|
||||||
Purpose: transmit string to UART
|
|
||||||
Input: string to be transmitted
|
|
||||||
Returns: none
|
|
||||||
**************************************************************************/
|
|
||||||
void uart_puts(const char *s )
|
|
||||||
{
|
|
||||||
while (*s)
|
|
||||||
uart_putc(*s++);
|
|
||||||
|
|
||||||
}/* uart_puts */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
Function: uart_puts_p()
|
|
||||||
Purpose: transmit string from program memory to UART
|
|
||||||
Input: program memory string to be transmitted
|
|
||||||
Returns: none
|
|
||||||
**************************************************************************/
|
|
||||||
void uart_puts_p(const char *progmem_s )
|
|
||||||
{
|
|
||||||
register char c;
|
|
||||||
|
|
||||||
while ( (c = pgm_read_byte(progmem_s++)) )
|
|
||||||
uart_putc(c);
|
|
||||||
|
|
||||||
}/* uart_puts_p */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* these functions are only for ATmegas with two USART
|
|
||||||
*/
|
|
||||||
#if defined( ATMEGA_USART1 )
|
|
||||||
|
|
||||||
SIGNAL(UART1_RECEIVE_INTERRUPT)
|
|
||||||
/*************************************************************************
|
|
||||||
Function: UART1 Receive Complete interrupt
|
|
||||||
Purpose: called when the UART1 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 = UART1_STATUS;
|
|
||||||
data = UART1_DATA;
|
|
||||||
|
|
||||||
/* */
|
|
||||||
lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );
|
|
||||||
|
|
||||||
/* calculate buffer index */
|
|
||||||
tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
|
|
||||||
|
|
||||||
if ( tmphead == UART1_RxTail ) {
|
|
||||||
/* error: receive buffer overflow */
|
|
||||||
lastRxError = UART_BUFFER_OVERFLOW >> 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<<U2X1); //Enable 2x speed
|
|
||||||
baudrate &= ~0x8000;
|
|
||||||
}
|
|
||||||
UBRR1H = (unsigned char)(baudrate>>8);
|
|
||||||
UBRR1L = (unsigned char) baudrate;
|
|
||||||
|
|
||||||
/* Enable USART receiver and transmitter and receive complete interrupt */
|
|
||||||
UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
|
|
||||||
|
|
||||||
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
|
||||||
#ifdef URSEL1
|
|
||||||
UCSR1C = (1<<URSEL1)|(3<<UCSZ10);
|
|
||||||
#else
|
|
||||||
UCSR1C = (3<<UCSZ10);
|
|
||||||
#endif
|
|
||||||
}/* uart_init */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
Function: uart1_getc()
|
|
||||||
Purpose: return byte from ringbuffer
|
|
||||||
Returns: lower byte: received byte from ringbuffer
|
|
||||||
higher byte: last receive error
|
|
||||||
**************************************************************************/
|
|
||||||
unsigned int uart1_getc(void)
|
|
||||||
{
|
|
||||||
unsigned char tmptail;
|
|
||||||
unsigned char data;
|
|
||||||
|
|
||||||
|
|
||||||
if ( UART1_RxHead == UART1_RxTail ) {
|
|
||||||
return UART_NO_DATA; /* no data available */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calculate /store buffer index */
|
|
||||||
tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;
|
|
||||||
UART1_RxTail = tmptail;
|
|
||||||
|
|
||||||
/* get data from receive buffer */
|
|
||||||
data = UART1_RxBuf[tmptail];
|
|
||||||
|
|
||||||
return (UART1_LastRxError << 8) + data;
|
|
||||||
|
|
||||||
}/* uart1_getc */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
Function: uart1_putc()
|
|
||||||
Purpose: write byte to ringbuffer for transmitting via UART
|
|
||||||
Input: byte to be transmitted
|
|
||||||
Returns: none
|
|
||||||
**************************************************************************/
|
|
||||||
void uart1_putc(unsigned char data)
|
|
||||||
{
|
|
||||||
unsigned char tmphead;
|
|
||||||
|
|
||||||
|
|
||||||
tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
|
|
||||||
|
|
||||||
while ( tmphead == UART1_TxTail ){
|
|
||||||
;/* wait for free space in buffer */
|
|
||||||
}
|
|
||||||
|
|
||||||
UART1_TxBuf[tmphead] = data;
|
|
||||||
UART1_TxHead = tmphead;
|
|
||||||
|
|
||||||
/* enable UDRE interrupt */
|
|
||||||
UART1_CONTROL |= _BV(UART1_UDRIE);
|
|
||||||
|
|
||||||
}/* uart1_putc */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
Function: uart1_puts()
|
|
||||||
Purpose: transmit string to UART1
|
|
||||||
Input: string to be transmitted
|
|
||||||
Returns: none
|
|
||||||
**************************************************************************/
|
|
||||||
void uart1_puts(const char *s )
|
|
||||||
{
|
|
||||||
while (*s)
|
|
||||||
uart1_putc(*s++);
|
|
||||||
|
|
||||||
}/* uart1_puts */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
Function: uart1_puts_p()
|
|
||||||
Purpose: transmit string from program memory to UART1
|
|
||||||
Input: program memory string to be transmitted
|
|
||||||
Returns: none
|
|
||||||
**************************************************************************/
|
|
||||||
void uart1_puts_p(const char *progmem_s )
|
|
||||||
{
|
|
||||||
register char c;
|
|
||||||
|
|
||||||
while ( (c = pgm_read_byte(progmem_s++)) )
|
|
||||||
uart1_putc(c);
|
|
||||||
|
|
||||||
}/* uart1_puts_p */
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,194 +0,0 @@
|
||||||
#ifndef UART_H
|
|
||||||
#define UART_H
|
|
||||||
/************************************************************************
|
|
||||||
Title: Interrupt UART library with receive/transmit circular buffers
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <uart.h> @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
|
|
||||||
* <br>no receive data available
|
|
||||||
* - \b UART_BUFFER_OVERFLOW
|
|
||||||
* <br>Receive ringbuffer overflow.
|
|
||||||
* We are not reading the receive buffer fast enough,
|
|
||||||
* one or more received character have been dropped
|
|
||||||
* - \b UART_OVERRUN_ERROR
|
|
||||||
* <br>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
|
|
||||||
* <br>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
|
|
||||||
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
##############################################################################
|
|
||||||
# #
|
|
||||||
# AVR-GCC skeleton #
|
|
||||||
# #
|
|
||||||
# by Triffid Hunter #
|
|
||||||
# #
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
# #
|
|
||||||
# Change these to suit your application #
|
|
||||||
# #
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
PROGRAM = yourprogramnamehere
|
|
||||||
|
|
||||||
SOURCES = $(PROGRAM).c ringbuffer.c serial.c lcd.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 -ffunction-sections -save-temps
|
|
||||||
LDFLAGS = -Wl,-u,vfprintf -lprintf_min -Wl,--as-needed -Wl,--gc-sections -finline-functions-called-once
|
|
||||||
|
|
||||||
CC = $(ARCH)gcc
|
|
||||||
OBJDUMP = $(ARCH)objdump
|
|
||||||
OBJCOPY = $(ARCH)objcopy
|
|
||||||
AVRDUDE = avrdude -F
|
|
||||||
|
|
||||||
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)
|
|
||||||
@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 *.i *.s *~
|
|
||||||
|
|
||||||
%.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 $< $@
|
|
||||||
104
skel/arduino.h
104
skel/arduino.h
|
|
@ -1,104 +0,0 @@
|
||||||
#ifndef _ARDUINO_H
|
|
||||||
#define _ARDUINO_H
|
|
||||||
|
|
||||||
#define PIN_DIO0 PD0
|
|
||||||
#define RPORT_DIO0 PIND
|
|
||||||
#define WPORT_DIO0 PORTD
|
|
||||||
#define DDR_DIO0 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO1 PD1
|
|
||||||
#define RPORT_DIO1 PIND
|
|
||||||
#define WPORT_DIO1 PORTD
|
|
||||||
#define DDR_DIO1 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO2 PD2
|
|
||||||
#define RPORT_DIO2 PIND
|
|
||||||
#define WPORT_DIO2 PORTD
|
|
||||||
#define DDR_DIO2 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO3 PD3
|
|
||||||
#define RPORT_DIO3 PIND
|
|
||||||
#define WPORT_DIO3 PORTD
|
|
||||||
#define DDR_DIO3 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO4 PD4
|
|
||||||
#define RPORT_DIO4 PIND
|
|
||||||
#define WPORT_DIO4 PORTD
|
|
||||||
#define DDR_DIO4 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO5 PD5
|
|
||||||
#define RPORT_DIO5 PIND
|
|
||||||
#define WPORT_DIO5 PORTD
|
|
||||||
#define DDR_DIO5 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO6 PD6
|
|
||||||
#define RPORT_DIO6 PIND
|
|
||||||
#define WPORT_DIO6 PORTD
|
|
||||||
#define DDR_DIO6 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO7 PD7
|
|
||||||
#define RPORT_DIO7 PIND
|
|
||||||
#define WPORT_DIO7 PORTD
|
|
||||||
#define DDR_DIO7 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO8 PB0
|
|
||||||
#define RPORT_DIO8 PINB
|
|
||||||
#define WPORT_DIO8 PORTB
|
|
||||||
#define DDR_DIO8 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO9 PB1
|
|
||||||
#define RPORT_DIO9 PINB
|
|
||||||
#define WPORT_DIO9 PORTB
|
|
||||||
#define DDR_DIO9 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO10 PB2
|
|
||||||
#define RPORT_DIO10 PINB
|
|
||||||
#define WPORT_DIO10 PORTB
|
|
||||||
#define DDR_DIO10 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO11 PB3
|
|
||||||
#define RPORT_DIO11 PINB
|
|
||||||
#define WPORT_DIO11 PORTB
|
|
||||||
#define DDR_DIO11 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO12 PB4
|
|
||||||
#define RPORT_DIO12 PINB
|
|
||||||
#define WPORT_DIO12 PORTB
|
|
||||||
#define DDR_DIO12 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO13 PB5
|
|
||||||
#define RPORT_DIO13 PINB
|
|
||||||
#define WPORT_DIO13 PORTB
|
|
||||||
#define DDR_DIO13 DDRB
|
|
||||||
|
|
||||||
#define PIN_AIO0 PC0
|
|
||||||
#define RPORT_AIO0 PINC
|
|
||||||
#define WPORT_AIO0 PORTC
|
|
||||||
#define DDR_AIO0 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO1 PC1
|
|
||||||
#define RPORT_AIO1 PINC
|
|
||||||
#define WPORT_AIO1 PORTC
|
|
||||||
#define DDR_AIO1 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO2 PC2
|
|
||||||
#define RPORT_AIO2 PINC
|
|
||||||
#define WPORT_AIO2 PORTC
|
|
||||||
#define DDR_AIO2 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO3 PC3
|
|
||||||
#define RPORT_AIO3 PINC
|
|
||||||
#define WPORT_AIO3 PORTC
|
|
||||||
#define DDR_AIO3 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO4 PC4
|
|
||||||
#define RPORT_AIO4 PINC
|
|
||||||
#define WPORT_AIO4 PORTC
|
|
||||||
#define DDR_AIO4 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO5 PC5
|
|
||||||
#define RPORT_AIO5 PINC
|
|
||||||
#define WPORT_AIO5 PORTC
|
|
||||||
#define DDR_AIO5 DDRC
|
|
||||||
|
|
||||||
#endif /* _ARDUINO_H */
|
|
||||||
595
skel/lcd.c
595
skel/lcd.c
|
|
@ -1,595 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
Title : HD44780U LCD library
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <inttypes.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#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 <us> 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 */
|
|
||||||
263
skel/lcd.h
263
skel/lcd.h
|
|
@ -1,263 +0,0 @@
|
||||||
#ifndef LCD_H
|
|
||||||
#define LCD_H
|
|
||||||
/*************************************************************************
|
|
||||||
Title : C include file for the HD44780U LCD library (lcd.c)
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <lcd.h> @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 <a href="http://homepage.sunrise.ch/mysunrise/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780 Based LCD to an AVR</a>
|
|
||||||
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 <inttypes.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Initialize display and select type of cursor
|
|
||||||
@param dispAttr \b LCD_DISP_OFF display off\n
|
|
||||||
\b LCD_DISP_ON display on, cursor off\n
|
|
||||||
\b LCD_DISP_ON_CURSOR display on, cursor on\n
|
|
||||||
\b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_init(uint8_t dispAttr);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Clear display and set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_clrscr(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_home(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to specified position
|
|
||||||
|
|
||||||
@param x horizontal position\n (0: left most position)
|
|
||||||
@param y vertical position\n (0: first line)
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_gotoxy(uint8_t x, uint8_t y);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display character at current cursor position
|
|
||||||
@param c character to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_putc(char c);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string without auto linefeed
|
|
||||||
@param s string to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_puts(const char *s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string from program memory without auto linefeed
|
|
||||||
@param s string from program memory be be displayed
|
|
||||||
@return none
|
|
||||||
@see lcd_puts_P
|
|
||||||
*/
|
|
||||||
void lcd_puts_p(const char *progmem_s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send LCD controller instruction command
|
|
||||||
@param cmd instruction to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_command(uint8_t cmd);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send data byte to LCD controller
|
|
||||||
|
|
||||||
Similar to lcd_putc(), but without interpreting LF
|
|
||||||
@param data byte to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_data(uint8_t data);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief macros for automatically storing string constant in program memory
|
|
||||||
*/
|
|
||||||
#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))
|
|
||||||
|
|
||||||
/*@}*/
|
|
||||||
#endif //LCD_H
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef _RINGBUFFER_H
|
|
||||||
#define _RINGBUFFER_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef _SERIAL_H
|
|
||||||
#define _SERIAL_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
|
|
||||||
#include "ringbuffer.h"
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#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, "MyProject OK");
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
##############################################################################
|
|
||||||
# #
|
|
||||||
# AVR-GCC skeleton #
|
|
||||||
# #
|
|
||||||
# by Triffid Hunter #
|
|
||||||
# #
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
# #
|
|
||||||
# Change these to suit your application #
|
|
||||||
# #
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
PROGRAM = stepper
|
|
||||||
|
|
||||||
SOURCES = $(PROGRAM).c ringbuffer.c serial.c lcd.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 -ffunction-sections -save-temps
|
|
||||||
LDFLAGS = -Wl,-u,vfprintf -lprintf_min -Wl,--as-needed -Wl,--gc-sections -finline-functions-called-once
|
|
||||||
|
|
||||||
CC = $(ARCH)gcc
|
|
||||||
OBJDUMP = $(ARCH)objdump
|
|
||||||
OBJCOPY = $(ARCH)objcopy
|
|
||||||
AVRDUDE = 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)
|
|
||||||
@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 *.i *.s *~
|
|
||||||
|
|
||||||
%.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 $< $@
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
#ifndef _ARDUINO_H
|
|
||||||
#define _ARDUINO_H
|
|
||||||
|
|
||||||
#define PIN_DIO0 PD0
|
|
||||||
#define RPORT_DIO0 PIND
|
|
||||||
#define WPORT_DIO0 PORTD
|
|
||||||
#define DDR_DIO0 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO1 PD1
|
|
||||||
#define RPORT_DIO1 PIND
|
|
||||||
#define WPORT_DIO1 PORTD
|
|
||||||
#define DDR_DIO1 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO2 PD2
|
|
||||||
#define RPORT_DIO2 PIND
|
|
||||||
#define WPORT_DIO2 PORTD
|
|
||||||
#define DDR_DIO2 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO3 PD3
|
|
||||||
#define RPORT_DIO3 PIND
|
|
||||||
#define WPORT_DIO3 PORTD
|
|
||||||
#define DDR_DIO3 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO4 PD4
|
|
||||||
#define RPORT_DIO4 PIND
|
|
||||||
#define WPORT_DIO4 PORTD
|
|
||||||
#define DDR_DIO4 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO5 PD5
|
|
||||||
#define RPORT_DIO5 PIND
|
|
||||||
#define WPORT_DIO5 PORTD
|
|
||||||
#define DDR_DIO5 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO6 PD6
|
|
||||||
#define RPORT_DIO6 PIND
|
|
||||||
#define WPORT_DIO6 PORTD
|
|
||||||
#define DDR_DIO6 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO7 PD7
|
|
||||||
#define RPORT_DIO7 PIND
|
|
||||||
#define WPORT_DIO7 PORTD
|
|
||||||
#define DDR_DIO7 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO8 PB0
|
|
||||||
#define RPORT_DIO8 PINB
|
|
||||||
#define WPORT_DIO8 PORTB
|
|
||||||
#define DDR_DIO8 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO9 PB1
|
|
||||||
#define RPORT_DIO9 PINB
|
|
||||||
#define WPORT_DIO9 PORTB
|
|
||||||
#define DDR_DIO9 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO10 PB2
|
|
||||||
#define RPORT_DIO10 PINB
|
|
||||||
#define WPORT_DIO10 PORTB
|
|
||||||
#define DDR_DIO10 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO11 PB3
|
|
||||||
#define RPORT_DIO11 PINB
|
|
||||||
#define WPORT_DIO11 PORTB
|
|
||||||
#define DDR_DIO11 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO12 PB4
|
|
||||||
#define RPORT_DIO12 PINB
|
|
||||||
#define WPORT_DIO12 PORTB
|
|
||||||
#define DDR_DIO12 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO13 PB5
|
|
||||||
#define RPORT_DIO13 PINB
|
|
||||||
#define WPORT_DIO13 PORTB
|
|
||||||
#define DDR_DIO13 DDRB
|
|
||||||
|
|
||||||
#define PIN_AIO0 PC0
|
|
||||||
#define RPORT_AIO0 PINC
|
|
||||||
#define WPORT_AIO0 PORTC
|
|
||||||
#define DDR_AIO0 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO1 PC1
|
|
||||||
#define RPORT_AIO1 PINC
|
|
||||||
#define WPORT_AIO1 PORTC
|
|
||||||
#define DDR_AIO1 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO2 PC2
|
|
||||||
#define RPORT_AIO2 PINC
|
|
||||||
#define WPORT_AIO2 PORTC
|
|
||||||
#define DDR_AIO2 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO3 PC3
|
|
||||||
#define RPORT_AIO3 PINC
|
|
||||||
#define WPORT_AIO3 PORTC
|
|
||||||
#define DDR_AIO3 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO4 PC4
|
|
||||||
#define RPORT_AIO4 PINC
|
|
||||||
#define WPORT_AIO4 PORTC
|
|
||||||
#define DDR_AIO4 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO5 PC5
|
|
||||||
#define RPORT_AIO5 PINC
|
|
||||||
#define WPORT_AIO5 PORTC
|
|
||||||
#define DDR_AIO5 DDRC
|
|
||||||
|
|
||||||
#endif /* _ARDUINO_H */
|
|
||||||
595
stepper-2/lcd.c
595
stepper-2/lcd.c
|
|
@ -1,595 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
Title : HD44780U LCD library
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <inttypes.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#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 <us> 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 */
|
|
||||||
263
stepper-2/lcd.h
263
stepper-2/lcd.h
|
|
@ -1,263 +0,0 @@
|
||||||
#ifndef LCD_H
|
|
||||||
#define LCD_H
|
|
||||||
/*************************************************************************
|
|
||||||
Title : C include file for the HD44780U LCD library (lcd.c)
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <lcd.h> @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 <a href="http://homepage.sunrise.ch/mysunrise/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780 Based LCD to an AVR</a>
|
|
||||||
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 <inttypes.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Initialize display and select type of cursor
|
|
||||||
@param dispAttr \b LCD_DISP_OFF display off\n
|
|
||||||
\b LCD_DISP_ON display on, cursor off\n
|
|
||||||
\b LCD_DISP_ON_CURSOR display on, cursor on\n
|
|
||||||
\b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_init(uint8_t dispAttr);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Clear display and set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_clrscr(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_home(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to specified position
|
|
||||||
|
|
||||||
@param x horizontal position\n (0: left most position)
|
|
||||||
@param y vertical position\n (0: first line)
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_gotoxy(uint8_t x, uint8_t y);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display character at current cursor position
|
|
||||||
@param c character to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_putc(char c);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string without auto linefeed
|
|
||||||
@param s string to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_puts(const char *s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string from program memory without auto linefeed
|
|
||||||
@param s string from program memory be be displayed
|
|
||||||
@return none
|
|
||||||
@see lcd_puts_P
|
|
||||||
*/
|
|
||||||
void lcd_puts_p(const char *progmem_s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send LCD controller instruction command
|
|
||||||
@param cmd instruction to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_command(uint8_t cmd);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send data byte to LCD controller
|
|
||||||
|
|
||||||
Similar to lcd_putc(), but without interpreting LF
|
|
||||||
@param data byte to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_data(uint8_t data);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief macros for automatically storing string constant in program memory
|
|
||||||
*/
|
|
||||||
#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))
|
|
||||||
|
|
||||||
/*@}*/
|
|
||||||
#endif //LCD_H
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef _RINGBUFFER_H
|
|
||||||
#define _RINGBUFFER_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#ifndef _SERIAL_H
|
|
||||||
#define _SERIAL_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
|
|
@ -1,302 +0,0 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#include "serial.h"
|
|
||||||
#include "lcd.h"
|
|
||||||
|
|
||||||
#include "arduino.h"
|
|
||||||
|
|
||||||
// *** pin assignments ***
|
|
||||||
|
|
||||||
// step input
|
|
||||||
#define PIN_STEP PIN_AIO2
|
|
||||||
#define PORT_STEP WPORT_AIO2
|
|
||||||
#define READ_STEP RPORT_AIO2
|
|
||||||
#define DDR_STEP DDR_AIO2
|
|
||||||
|
|
||||||
// direction input
|
|
||||||
#define PIN_DIR PIN_AIO3
|
|
||||||
#define PORT_DIR WPORT_AIO3
|
|
||||||
#define READ_DIR RPORT_AIO3
|
|
||||||
#define DDR_DIR DDR_AIO3
|
|
||||||
|
|
||||||
// step output
|
|
||||||
#define PIN_STEPOUT PIN_AIO4
|
|
||||||
#define PORT_STEPOUT WPORT_AIO4
|
|
||||||
#define READ_STEPOUT RPORT_AIO4
|
|
||||||
#define DDR_STEPOUT DDR_AIO4
|
|
||||||
|
|
||||||
// direction output
|
|
||||||
#define PIN_DIROUT PIN_AIO5
|
|
||||||
#define PORT_DIROUT WPORT_AIO5
|
|
||||||
#define READ_DIROUT RPORT_AIO5
|
|
||||||
#define DDR_DIROUT DDR_AIO5
|
|
||||||
|
|
||||||
// *** machine-specific constants ***
|
|
||||||
|
|
||||||
// 1/2 step, NSTEPPING=2, for 1/4 step, NSTEPPING = 4 etc
|
|
||||||
#define NSTEPPING 16
|
|
||||||
|
|
||||||
// FULL steps per mm (calculate from 200 steps/rev)
|
|
||||||
#define FULL_STEPS_PER_MM 5
|
|
||||||
|
|
||||||
// calculations
|
|
||||||
#define PRESCALER 256
|
|
||||||
#define STEPS_PER_MM (FULL_STEPS_PER_MM * NSTEPPING)
|
|
||||||
|
|
||||||
// units
|
|
||||||
#define MM * STEPS_PER_MM
|
|
||||||
#define MM_PER_SEC * STEPS_PER_MM
|
|
||||||
|
|
||||||
#define US * F_CPU / 1000000 / PRESCALER
|
|
||||||
#define MS * F_CPU / 1000 / PRESCALER
|
|
||||||
#define S * F_CPU / 1 / PRESCALER
|
|
||||||
|
|
||||||
// *** tunables ***
|
|
||||||
|
|
||||||
#define SPEED (15 MM_PER_SEC)
|
|
||||||
|
|
||||||
// recalculations - don't touch!
|
|
||||||
#define STEP_TIME F_CPU / SPEED / PRESCALER
|
|
||||||
#define MIN_STEP_TIME F_CPU / 1000 / PRESCALER
|
|
||||||
|
|
||||||
// utilities
|
|
||||||
#define MASK(a) (1 << a)
|
|
||||||
#define PORT_OUT_MASK (0xF << PIN_LSB_OUT)
|
|
||||||
#define abs(a) (((a) >= 0)?(a):-(a))
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
volatile int32_t pos;
|
|
||||||
volatile int32_t npos;
|
|
||||||
volatile uint16_t speed;
|
|
||||||
|
|
||||||
// next step interrupt
|
|
||||||
ISR(TIMER1_COMPA_vect) {
|
|
||||||
// toggle "L" led
|
|
||||||
PINB = MASK(PB5);
|
|
||||||
|
|
||||||
if (READ_STEPOUT & MASK(PIN_STEPOUT)) {
|
|
||||||
if (npos > pos)
|
|
||||||
PORT_DIROUT |= MASK(PIN_DIROUT);
|
|
||||||
else if (npos < pos)
|
|
||||||
PORT_DIROUT &= ~MASK(PIN_DIROUT);
|
|
||||||
else
|
|
||||||
TIMSK1 &= ~MASK(OCIE1A);
|
|
||||||
|
|
||||||
PORT_STEPOUT &= ~MASK(PIN_STEPOUT);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PORT_STEPOUT |= MASK(PIN_STEPOUT);
|
|
||||||
|
|
||||||
if (READ_DIROUT & MASK(PIN_DIROUT))
|
|
||||||
pos++;
|
|
||||||
else
|
|
||||||
pos--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update speed
|
|
||||||
OCR1A = speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startstep(void) {
|
|
||||||
if ((TIMSK1 & MASK(OCIE1A)) == 0)
|
|
||||||
{
|
|
||||||
OCR1A = speed;
|
|
||||||
TCNT1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// it's possible that the mask is enabled during the check above, but disabled by the time we get here - always set it to avoid a race condition
|
|
||||||
TIMSK1 |= MASK(OCIE1A);
|
|
||||||
}
|
|
||||||
|
|
||||||
// main, where it all happens
|
|
||||||
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);
|
|
||||||
|
|
||||||
// variables
|
|
||||||
pos = 0;
|
|
||||||
uint8_t stepdebounce = 0;
|
|
||||||
uint16_t spinner = 0;
|
|
||||||
int r;
|
|
||||||
int32_t rv;
|
|
||||||
uint8_t input_lastreading;
|
|
||||||
|
|
||||||
// setup inputs
|
|
||||||
DDR_STEP &= ~MASK(PIN_STEP);
|
|
||||||
DDR_DIR &= ~MASK(PIN_DIR);
|
|
||||||
|
|
||||||
// pull-ups
|
|
||||||
PORT_STEP |= MASK(PIN_STEP);
|
|
||||||
PORT_DIR |= MASK(PIN_DIR);
|
|
||||||
|
|
||||||
// noise rejection
|
|
||||||
WPORT_AIO0 |= MASK(PIN_AIO0);
|
|
||||||
WPORT_AIO1 |= MASK(PIN_AIO1);
|
|
||||||
|
|
||||||
// outputs to motor controller
|
|
||||||
PORT_STEPOUT &= ~MASK(PIN_STEPOUT);
|
|
||||||
PORT_DIROUT &= ~MASK(PIN_DIROUT);
|
|
||||||
DDR_STEPOUT |= MASK(PIN_STEPOUT);
|
|
||||||
DDR_DIROUT |= MASK(PIN_DIROUT);
|
|
||||||
|
|
||||||
// setup timer 1 (step timer)
|
|
||||||
TCCR1A = 0;
|
|
||||||
TCCR1B = MASK(WGM12);
|
|
||||||
#if PRESCALER == 1
|
|
||||||
TCCR1B |= MASK(CS10);
|
|
||||||
#elif PRESCALER == 8
|
|
||||||
TCCR1B |= MASK(CS11);
|
|
||||||
#elif PRESCALER == 64
|
|
||||||
TCCR1B |= MASK(CS11) | MASK(CS10);
|
|
||||||
#elif PRESCALER == 256
|
|
||||||
TCCR1B |= MASK(CS12);
|
|
||||||
#elif PRESCALER == 1024
|
|
||||||
TCCR1B |= MASK(CS12) | MASK(CS10);
|
|
||||||
#else
|
|
||||||
#error Invalid PRESCALER value: must be one of 1, 8, 64, 256 or 1024
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// disable interrupt
|
|
||||||
TIMSK1 = 0;
|
|
||||||
|
|
||||||
// set speed: divide by 2 because we toggle each interrupt rather than full pulse
|
|
||||||
speed = STEP_TIME / 2;
|
|
||||||
OCR1A = speed;
|
|
||||||
|
|
||||||
// enable interrupts
|
|
||||||
sei();
|
|
||||||
|
|
||||||
// main loop start
|
|
||||||
lcd_gotoxy(0, 0);
|
|
||||||
fprintf(&lcdo, "Stepper OK ");
|
|
||||||
|
|
||||||
// main loop
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
// check logic inputs
|
|
||||||
if (1) {
|
|
||||||
uint8_t input_thisreading = (READ_STEP & (MASK(PIN_STEP) | MASK(PIN_DIR)));
|
|
||||||
// if same as last time
|
|
||||||
if (input_thisreading == input_lastreading) {
|
|
||||||
// if we're near debounce threshold
|
|
||||||
if (stepdebounce >= 32) {
|
|
||||||
// if we're exactly on the threshold
|
|
||||||
if (stepdebounce == 32) {
|
|
||||||
// adjust target position
|
|
||||||
if (input_thisreading & MASK(PIN_DIR))
|
|
||||||
npos++;
|
|
||||||
else
|
|
||||||
npos--;
|
|
||||||
// go over threshold so inputs must change before next move
|
|
||||||
stepdebounce++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// approach threshold
|
|
||||||
else {
|
|
||||||
stepdebounce++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if input changed, reset debouncer
|
|
||||||
else {
|
|
||||||
stepdebounce = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check serial input
|
|
||||||
if (serial_rxchars()) {
|
|
||||||
uint8_t c = getchar();
|
|
||||||
switch (c) {
|
|
||||||
case '>':
|
|
||||||
npos++;
|
|
||||||
break;
|
|
||||||
case '<':
|
|
||||||
npos--;
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
fprintf(&serio, "pos:%li\n", pos);
|
|
||||||
break;
|
|
||||||
case '+':
|
|
||||||
r = scanf("%li", &rv);
|
|
||||||
if (r == 0)
|
|
||||||
npos++;
|
|
||||||
else
|
|
||||||
npos += rv;
|
|
||||||
break;
|
|
||||||
case '-':
|
|
||||||
r = scanf("%li", &rv);
|
|
||||||
if (r == 0)
|
|
||||||
npos--;
|
|
||||||
else
|
|
||||||
npos -= rv;
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
if (scanf("%li", &rv))
|
|
||||||
npos = rv;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
if (scanf("%li", &rv))
|
|
||||||
speed = rv;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
npos = 0;
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
npos = pos = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((npos != pos) && ((TIMSK1 & MASK(OCIE1A)) == 0))
|
|
||||||
startstep();
|
|
||||||
|
|
||||||
if (((spinner++) & 0x0FFF) == 0) {
|
|
||||||
lcd_clrscr();
|
|
||||||
printf("p:%7li", pos);
|
|
||||||
lcd_gotoxy(8, 0);
|
|
||||||
printf("s:%i", speed);
|
|
||||||
lcd_gotoxy(0, 1);
|
|
||||||
printf("t:%7li", npos);
|
|
||||||
lcd_gotoxy(8, 1);
|
|
||||||
// printf("p:%i", PORT_STEP);
|
|
||||||
// printf("%i %i", step1, step2);
|
|
||||||
printf("%02X", READ_STEP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
##############################################################################
|
|
||||||
# #
|
|
||||||
# AVR-GCC skeleton #
|
|
||||||
# #
|
|
||||||
# by Triffid Hunter #
|
|
||||||
# #
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
# #
|
|
||||||
# Change these to suit your application #
|
|
||||||
# #
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
PROGRAM = stepper
|
|
||||||
|
|
||||||
SOURCES = $(PROGRAM).c ringbuffer.c serial.c lcd.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 -ffunction-sections -save-temps
|
|
||||||
LDFLAGS = -Wl,-u,vfprintf -lprintf_min -Wl,--as-needed -Wl,--gc-sections -finline-functions-called-once
|
|
||||||
|
|
||||||
CC = $(ARCH)gcc
|
|
||||||
OBJDUMP = $(ARCH)objdump
|
|
||||||
OBJCOPY = $(ARCH)objcopy
|
|
||||||
AVRDUDE = avrdude -F
|
|
||||||
|
|
||||||
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)
|
|
||||||
@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 $< $@
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
#ifndef _ARDUINO_H
|
|
||||||
#define _ARDUINO_H
|
|
||||||
|
|
||||||
#define PIN_DIO0 PD0
|
|
||||||
#define RPORT_DIO0 PIND
|
|
||||||
#define WPORT_DIO0 PORTD
|
|
||||||
#define DDR_DIO0 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO1 PD1
|
|
||||||
#define RPORT_DIO1 PIND
|
|
||||||
#define WPORT_DIO1 PORTD
|
|
||||||
#define DDR_DIO1 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO2 PD2
|
|
||||||
#define RPORT_DIO2 PIND
|
|
||||||
#define WPORT_DIO2 PORTD
|
|
||||||
#define DDR_DIO2 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO3 PD3
|
|
||||||
#define RPORT_DIO3 PIND
|
|
||||||
#define WPORT_DIO3 PORTD
|
|
||||||
#define DDR_DIO3 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO4 PD4
|
|
||||||
#define RPORT_DIO4 PIND
|
|
||||||
#define WPORT_DIO4 PORTD
|
|
||||||
#define DDR_DIO4 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO5 PD5
|
|
||||||
#define RPORT_DIO5 PIND
|
|
||||||
#define WPORT_DIO5 PORTD
|
|
||||||
#define DDR_DIO5 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO6 PD6
|
|
||||||
#define RPORT_DIO6 PIND
|
|
||||||
#define WPORT_DIO6 PORTD
|
|
||||||
#define DDR_DIO6 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO7 PD7
|
|
||||||
#define RPORT_DIO7 PIND
|
|
||||||
#define WPORT_DIO7 PORTD
|
|
||||||
#define DDR_DIO7 DDRD
|
|
||||||
|
|
||||||
#define PIN_DIO8 PB0
|
|
||||||
#define RPORT_DIO8 PINB
|
|
||||||
#define WPORT_DIO8 PORTB
|
|
||||||
#define DDR_DIO8 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO9 PB1
|
|
||||||
#define RPORT_DIO9 PINB
|
|
||||||
#define WPORT_DIO9 PORTB
|
|
||||||
#define DDR_DIO9 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO10 PB2
|
|
||||||
#define RPORT_DIO10 PINB
|
|
||||||
#define WPORT_DIO10 PORTB
|
|
||||||
#define DDR_DIO10 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO11 PB3
|
|
||||||
#define RPORT_DIO11 PINB
|
|
||||||
#define WPORT_DIO11 PORTB
|
|
||||||
#define DDR_DIO11 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO12 PB4
|
|
||||||
#define RPORT_DIO12 PINB
|
|
||||||
#define WPORT_DIO12 PORTB
|
|
||||||
#define DDR_DIO12 DDRB
|
|
||||||
|
|
||||||
#define PIN_DIO13 PB5
|
|
||||||
#define RPORT_DIO13 PINB
|
|
||||||
#define WPORT_DIO13 PORTB
|
|
||||||
#define DDR_DIO13 DDRB
|
|
||||||
|
|
||||||
#define PIN_AIO0 PC0
|
|
||||||
#define RPORT_AIO0 PINC
|
|
||||||
#define WPORT_AIO0 PORTC
|
|
||||||
#define DDR_AIO0 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO1 PC1
|
|
||||||
#define RPORT_AIO1 PINC
|
|
||||||
#define WPORT_AIO1 PORTC
|
|
||||||
#define DDR_AIO1 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO2 PC2
|
|
||||||
#define RPORT_AIO2 PINC
|
|
||||||
#define WPORT_AIO2 PORTC
|
|
||||||
#define DDR_AIO2 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO3 PC3
|
|
||||||
#define RPORT_AIO3 PINC
|
|
||||||
#define WPORT_AIO3 PORTC
|
|
||||||
#define DDR_AIO3 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO4 PC4
|
|
||||||
#define RPORT_AIO4 PINC
|
|
||||||
#define WPORT_AIO4 PORTC
|
|
||||||
#define DDR_AIO4 DDRC
|
|
||||||
|
|
||||||
#define PIN_AIO5 PC5
|
|
||||||
#define RPORT_AIO5 PINC
|
|
||||||
#define WPORT_AIO5 PORTC
|
|
||||||
#define DDR_AIO5 DDRC
|
|
||||||
|
|
||||||
#endif /* _ARDUINO_H */
|
|
||||||
595
stepper/lcd.c
595
stepper/lcd.c
|
|
@ -1,595 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
Title : HD44780U LCD library
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <inttypes.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#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 <us> 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 */
|
|
||||||
263
stepper/lcd.h
263
stepper/lcd.h
|
|
@ -1,263 +0,0 @@
|
||||||
#ifndef LCD_H
|
|
||||||
#define LCD_H
|
|
||||||
/*************************************************************************
|
|
||||||
Title : C include file for the HD44780U LCD library (lcd.c)
|
|
||||||
Author: Peter Fleury <pfleury@gmx.ch> 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 <lcd.h> @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 <a href="http://homepage.sunrise.ch/mysunrise/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780 Based LCD to an AVR</a>
|
|
||||||
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 <inttypes.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Initialize display and select type of cursor
|
|
||||||
@param dispAttr \b LCD_DISP_OFF display off\n
|
|
||||||
\b LCD_DISP_ON display on, cursor off\n
|
|
||||||
\b LCD_DISP_ON_CURSOR display on, cursor on\n
|
|
||||||
\b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_init(uint8_t dispAttr);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Clear display and set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_clrscr(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to home position
|
|
||||||
@param void
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_home(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Set cursor to specified position
|
|
||||||
|
|
||||||
@param x horizontal position\n (0: left most position)
|
|
||||||
@param y vertical position\n (0: first line)
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_gotoxy(uint8_t x, uint8_t y);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display character at current cursor position
|
|
||||||
@param c character to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_putc(char c);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string without auto linefeed
|
|
||||||
@param s string to be displayed
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_puts(const char *s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Display string from program memory without auto linefeed
|
|
||||||
@param s string from program memory be be displayed
|
|
||||||
@return none
|
|
||||||
@see lcd_puts_P
|
|
||||||
*/
|
|
||||||
void lcd_puts_p(const char *progmem_s);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send LCD controller instruction command
|
|
||||||
@param cmd instruction to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_command(uint8_t cmd);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Send data byte to LCD controller
|
|
||||||
|
|
||||||
Similar to lcd_putc(), but without interpreting LF
|
|
||||||
@param data byte to send to LCD controller, see HD44780 data sheet
|
|
||||||
@return none
|
|
||||||
*/
|
|
||||||
void lcd_data(uint8_t data);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief macros for automatically storing string constant in program memory
|
|
||||||
*/
|
|
||||||
#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))
|
|
||||||
|
|
||||||
/*@}*/
|
|
||||||
#endif //LCD_H
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef _RINGBUFFER_H
|
|
||||||
#define _RINGBUFFER_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#ifndef _SERIAL_H
|
|
||||||
#define _SERIAL_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
|
|
@ -1,396 +0,0 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#include "serial.h"
|
|
||||||
#include "lcd.h"
|
|
||||||
|
|
||||||
#include "arduino.h"
|
|
||||||
|
|
||||||
// *** pin assignments ***
|
|
||||||
|
|
||||||
// step input
|
|
||||||
#define PIN_STEP PIN_AIO2
|
|
||||||
#define PORT_STEP WPORT_AIO2
|
|
||||||
#define READ_STEP RPORT_AIO2
|
|
||||||
#define DDR_STEP DDR_AIO2
|
|
||||||
|
|
||||||
// direction input
|
|
||||||
#define PIN_DIR PIN_AIO3
|
|
||||||
#define PORT_DIR WPORT_AIO3
|
|
||||||
#define READ_DIR RPORT_AIO3
|
|
||||||
#define DDR_DIR DDR_AIO3
|
|
||||||
|
|
||||||
// outputs (PWM) - dir lines only below, en lines MUST connect to OCR0A/B (DIO 5/6)
|
|
||||||
#define PIN_DIR1 PIN_AIO0
|
|
||||||
#define PORT_DIR1 WPORT_AIO0
|
|
||||||
#define DDR_DIR1 DDR_AIO0
|
|
||||||
|
|
||||||
#define PIN_DIR2 PIN_AIO1
|
|
||||||
#define PORT_DIR2 WPORT_AIO1
|
|
||||||
#define DDR_DIR2 DDR_AIO1
|
|
||||||
|
|
||||||
|
|
||||||
// *** machine-specific constants ***
|
|
||||||
|
|
||||||
// 1/2 step, NSTEPPING=2, for 1/4 step, NSTEPPING = 4 etc
|
|
||||||
#define NSTEPPING 8
|
|
||||||
// FULL steps per mm (calculate from 200 steps/rev)
|
|
||||||
#define FULL_STEPS_PER_MM 5
|
|
||||||
|
|
||||||
// calculations
|
|
||||||
#define PRESCALER 256
|
|
||||||
#define STEPS_PER_MM (FULL_STEPS_PER_MM * NSTEPPING)
|
|
||||||
|
|
||||||
// units
|
|
||||||
#define MM * STEPS_PER_MM
|
|
||||||
#define MM_PER_SEC * STEPS_PER_MM
|
|
||||||
|
|
||||||
#define US * F_CPU / 1000000 / PRESCALER
|
|
||||||
#define MS * F_CPU / 1000 / PRESCALER
|
|
||||||
#define S * F_CPU / 1 / PRESCALER
|
|
||||||
|
|
||||||
// *** tunables ***
|
|
||||||
|
|
||||||
#define SPEED (15 MM_PER_SEC)
|
|
||||||
|
|
||||||
// *** step table ***
|
|
||||||
// sinstepi MUST satisfy 2^n for integer values of n where n = 2 for 1/2 step, 4 for 1/4 step etc
|
|
||||||
// generate with:
|
|
||||||
// perl -e 'my $n = 4; my @st; for (0..$n) { push @st, sprintf "%i", sin($_ * 90 * 3.1415926535897932384626433832795029 * 2 / 360 / $n) * 255 }; print "#define sinstepi $n\nstatic uint8_t sintable[sinstepi + 1] = { "; print join ", ", @st; print " };\n";';
|
|
||||||
|
|
||||||
#if NSTEPPING == 1
|
|
||||||
#define sinstepi 1
|
|
||||||
static const uint8_t sintable[sinstepi + 1] = { 0, 255 };
|
|
||||||
|
|
||||||
#elif NSTEPPING == 2
|
|
||||||
#define sinstepi 2
|
|
||||||
static const uint8_t sintable[sinstepi + 1] = { 0, 180, 255 };
|
|
||||||
|
|
||||||
#elif NSTEPPING == 4
|
|
||||||
#define sinstepi 4
|
|
||||||
static uint8_t sintable[sinstepi + 1] = { 0, 97, 180, 235, 255 };
|
|
||||||
|
|
||||||
#elif NSTEPPING == 8
|
|
||||||
#define sinstepi 8
|
|
||||||
static uint8_t sintable[sinstepi + 1] = { 0, 49, 97, 141, 180, 212, 235, 250, 255 };
|
|
||||||
|
|
||||||
#elif NSTEPPING == 16
|
|
||||||
#define sinstepi 16
|
|
||||||
static uint8_t sintable[sinstepi + 1] = { 0, 24, 49, 74, 97, 120, 141, 161, 180, 197, 212, 224, 235, 244, 250, 253, 255 };
|
|
||||||
|
|
||||||
#elif NSTEPPING == 32
|
|
||||||
#define sinstepi 32
|
|
||||||
static uint8_t sintable[sinstepi + 1] = { 0, 12, 24, 37, 49, 61, 74, 85, 97, 109, 120, 131, 141, 151, 161, 171, 180, 188, 197, 204, 212, 218, 224, 230, 235, 240, 244, 247, 250, 252, 253, 254, 255 };
|
|
||||||
|
|
||||||
#else
|
|
||||||
#error Invalid NSTEPPING value
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// recalculations - don't touch!
|
|
||||||
#define STEP_TIME F_CPU / SPEED / PRESCALER
|
|
||||||
#define MIN_STEP_TIME F_CPU / 1000 / PRESCALER
|
|
||||||
#define sinstepi2 (sinstepi * 2)
|
|
||||||
#define sinstepi3 (sinstepi * 3)
|
|
||||||
#define sinstepi4 (sinstepi * 4)
|
|
||||||
#define sinsteplast (sinstepi4 - 1)
|
|
||||||
|
|
||||||
// utilities
|
|
||||||
#define MASK(a) (1 << a)
|
|
||||||
#define PORT_OUT_MASK (0xF << PIN_LSB_OUT)
|
|
||||||
#define abs(a) (((a) >= 0)?(a):-(a))
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
volatile int32_t pos;
|
|
||||||
volatile int32_t npos;
|
|
||||||
volatile uint16_t speed;
|
|
||||||
volatile uint16_t speed_sync;
|
|
||||||
volatile uint8_t superstep; // for disabling microstep during high speed runs
|
|
||||||
volatile uint8_t superstep_sync;
|
|
||||||
volatile int step1;
|
|
||||||
volatile int step2;
|
|
||||||
// uint8_t power0;
|
|
||||||
// uint8_t power1;
|
|
||||||
|
|
||||||
// integer sine approximation
|
|
||||||
int sinstep(uint8_t sequence) {
|
|
||||||
while (sequence >= sinstepi4)
|
|
||||||
sequence -= sinstepi4;
|
|
||||||
if (sequence < (sinstepi + 1))
|
|
||||||
return sintable[sequence];
|
|
||||||
if ((sequence >= (sinstepi + 1)) && (sequence < (sinstepi2 + 1)))
|
|
||||||
return sintable[sinstepi2 - sequence];
|
|
||||||
if ((sequence >= (sinstepi2 + 1)) && (sequence < (sinstepi3 + 1)))
|
|
||||||
return -sintable[sequence - sinstepi2];
|
|
||||||
//if ((sequence >= (sinstepi3 + 1)) && (sequence < (sinstepi4 + 1)))
|
|
||||||
return -sintable[sinstepi4 - sequence];
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate appropriate stepper signals for a sequence number
|
|
||||||
void stepperseq(uint8_t sequence) {
|
|
||||||
step1 = sinstep(sequence);
|
|
||||||
step2 = sinstep(sequence + sinstepi);
|
|
||||||
|
|
||||||
// set directions
|
|
||||||
if (step1 >= 0)
|
|
||||||
PORT_DIR1 |= MASK(PIN_DIR1);
|
|
||||||
else {
|
|
||||||
PORT_DIR1 &= ~MASK(PIN_DIR1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// PORT_DIR1 = (PORT_DIR1 & ~MASK(PIN_DIR1)) | ((((step1 >= 0)?255:0) ^ wx) & MASK(PIN_DIR1));
|
|
||||||
|
|
||||||
if (step2 >= 0)
|
|
||||||
PORT_DIR2 |= MASK(PIN_DIR2);
|
|
||||||
else {
|
|
||||||
PORT_DIR2 &= ~MASK(PIN_DIR2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// PORT_DIR2 = (PORT_DIR2 & ~MASK(PIN_DIR2)) | ((((step2 >= 0)?255:0) ^ wx) & MASK(PIN_DIR2));
|
|
||||||
|
|
||||||
// set power
|
|
||||||
TCNT0 = 0xFD;
|
|
||||||
OCR0A = ((uint8_t) abs(step1));
|
|
||||||
OCR0B = ((uint8_t) abs(step2));
|
|
||||||
}
|
|
||||||
|
|
||||||
// // PWM reset interrupt
|
|
||||||
// ISR(TIMER0_OVF_vect) {
|
|
||||||
// // now that our counter is at zero, load new power levels
|
|
||||||
// OCR0A = power0;
|
|
||||||
// OCR0B = power1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// next step interrupt
|
|
||||||
ISR(TIMER1_COMPA_vect) {
|
|
||||||
uint8_t i;
|
|
||||||
|
|
||||||
// toggle "L" led
|
|
||||||
PINB = MASK(PB5);
|
|
||||||
|
|
||||||
// update position
|
|
||||||
if (npos > pos)
|
|
||||||
pos += MASK(superstep_sync);
|
|
||||||
else if (npos < pos)
|
|
||||||
pos -= MASK(superstep_sync);
|
|
||||||
|
|
||||||
// write new position
|
|
||||||
i = pos & sinsteplast;
|
|
||||||
stepperseq(i);
|
|
||||||
// if we're at a sync point and we're changing microstep rate
|
|
||||||
if ((i & (sinstepi2 - 1)) == 0)
|
|
||||||
// do the change now
|
|
||||||
superstep_sync = superstep;
|
|
||||||
// update speed
|
|
||||||
OCR1A = speed << superstep_sync;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startstep(void) {
|
|
||||||
if ((TIMSK1 & MASK(OCIE1A)) == 0)
|
|
||||||
{
|
|
||||||
OCR1A = speed;
|
|
||||||
// while ((OCR1A < MIN_STEP_TIME) && (superstep < sinstepi)) {
|
|
||||||
// OCR1A <<= 1;
|
|
||||||
// superstep <<= 1;
|
|
||||||
// }
|
|
||||||
// while (((OCR1A > (MIN_STEP_TIME * 2)) && (superstep > 1)) || (abs(npos - pos) < superstep)) {
|
|
||||||
// OCR1A >>= 1;
|
|
||||||
// superstep >>= 1;
|
|
||||||
// }
|
|
||||||
TCNT1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// it's possible that the mask is enabled during the check above, but disabled by the time we get here - always set it to avoid a race condition
|
|
||||||
TIMSK1 |= MASK(OCIE1A);
|
|
||||||
}
|
|
||||||
|
|
||||||
// main, where it all happens
|
|
||||||
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);
|
|
||||||
|
|
||||||
// variables
|
|
||||||
pos = 0;
|
|
||||||
uint8_t stepdebounce = 0;
|
|
||||||
uint16_t spinner = 0;
|
|
||||||
int r;
|
|
||||||
int32_t rv;
|
|
||||||
int rs;
|
|
||||||
|
|
||||||
// setup inputs
|
|
||||||
DDR_STEP &= ~MASK(PIN_STEP);
|
|
||||||
DDR_DIR &= ~MASK(PIN_DIR);
|
|
||||||
|
|
||||||
// pull-ups
|
|
||||||
PORT_STEP |= MASK(PIN_STEP);
|
|
||||||
PORT_DIR |= MASK(PIN_DIR);
|
|
||||||
|
|
||||||
// direction pins to h-bridge
|
|
||||||
DDR_DIR1 |= MASK(PIN_DIR1);
|
|
||||||
DDR_DIR2 |= MASK(PIN_DIR2);
|
|
||||||
// enable pins to h-bridge - must be DIO5/6 for PWM operation
|
|
||||||
DDR_DIO5 |= MASK(PIN_DIO5);
|
|
||||||
DDR_DIO6 |= MASK(PIN_DIO6);
|
|
||||||
|
|
||||||
// setup timer 0 (PWM timer)
|
|
||||||
TCCR0A = MASK(COM0A1) | MASK(COM0B1) | MASK(WGM01) | MASK(WGM00); // enable PWM output pins (DIO5/6), fast PWM
|
|
||||||
TCCR0B = MASK(CS00); // prescaler = 1 (max speed)
|
|
||||||
|
|
||||||
// setup timer 1 (step timer)
|
|
||||||
TCCR1A = 0;
|
|
||||||
TCCR1B = MASK(WGM12);
|
|
||||||
#if PRESCALER == 1
|
|
||||||
TCCR1B |= MASK(CS10);
|
|
||||||
#elif PRESCALER == 8
|
|
||||||
TCCR1B |= MASK(CS11);
|
|
||||||
#elif PRESCALER == 64
|
|
||||||
TCCR1B |= MASK(CS11) | MASK(CS10);
|
|
||||||
#elif PRESCALER == 256
|
|
||||||
TCCR1B |= MASK(CS12);
|
|
||||||
#elif PRESCALER == 1024
|
|
||||||
TCCR1B |= MASK(CS12) | MASK(CS10);
|
|
||||||
#else
|
|
||||||
#error Invalid PRESCALER value: must be one of 1, 8, 64, 256 or 1024
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// disable interrupt
|
|
||||||
TIMSK1 = 0;
|
|
||||||
// set speed
|
|
||||||
speed = STEP_TIME;
|
|
||||||
OCR1A = speed << superstep;
|
|
||||||
|
|
||||||
// initialize stepper drive
|
|
||||||
//PORT_OUT = (PORT_OUT & ~PORT_OUT_MASK) | ((steps[0] ^ wmod) << PIN_LSB_OUT);
|
|
||||||
stepperseq(0);
|
|
||||||
|
|
||||||
// enable interrupts
|
|
||||||
sei();
|
|
||||||
|
|
||||||
// main loop start
|
|
||||||
lcd_gotoxy(0, 0);
|
|
||||||
fprintf(&lcdo, "Stepper OK ");
|
|
||||||
|
|
||||||
// main loop
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
// check logic inputs
|
|
||||||
if ((READ_STEP & MASK(PIN_STEP)) == 0) {
|
|
||||||
if (stepdebounce >= 32) {
|
|
||||||
if (stepdebounce == 32) {
|
|
||||||
if (READ_DIR & MASK(PIN_DIR))
|
|
||||||
npos++;
|
|
||||||
else
|
|
||||||
npos--;
|
|
||||||
stepdebounce++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
stepdebounce++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
stepdebounce = 0;
|
|
||||||
|
|
||||||
// check serial input
|
|
||||||
if (serial_rxchars()) {
|
|
||||||
uint8_t c = getchar();
|
|
||||||
switch (c) {
|
|
||||||
case '>':
|
|
||||||
npos++;
|
|
||||||
break;
|
|
||||||
case '<':
|
|
||||||
npos--;
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
fprintf(&serio, "pos:%li\n", pos);
|
|
||||||
break;
|
|
||||||
case '+':
|
|
||||||
r = scanf("%li", &rv);
|
|
||||||
if (r == 0)
|
|
||||||
npos++;
|
|
||||||
else
|
|
||||||
npos += rv;
|
|
||||||
break;
|
|
||||||
case '-':
|
|
||||||
r = scanf("%li", &rv);
|
|
||||||
if (r == 0)
|
|
||||||
npos--;
|
|
||||||
else
|
|
||||||
npos -= rv;
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
r = scanf("%li", &rv);
|
|
||||||
if (r != 0)
|
|
||||||
npos = rv;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
r = scanf("%li", &rv);
|
|
||||||
if (r != 0)
|
|
||||||
speed = rv;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
npos = 0;
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
r = scanf("%i", &rs);
|
|
||||||
if (r != 0)
|
|
||||||
superstep = rs;
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
npos = pos = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((npos != pos) && ((TIMSK1 & MASK(OCIE1A)) == 0))
|
|
||||||
startstep();
|
|
||||||
|
|
||||||
if (((spinner++) & 0x0FFF) == 0) {
|
|
||||||
lcd_clrscr();
|
|
||||||
printf("p:%7li", pos);
|
|
||||||
lcd_gotoxy(8, 0);
|
|
||||||
printf("s:%i", speed);
|
|
||||||
lcd_gotoxy(0, 1);
|
|
||||||
printf("t:%7li", npos);
|
|
||||||
lcd_gotoxy(8, 1);
|
|
||||||
// printf("p:%i", PORT_STEP);
|
|
||||||
printf("%i %i", step1, step2);
|
|
||||||
// printf("%02X", READ_STEP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
//
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
// generate with:
|
|
||||||
// perl -e 'my $n = 16; my @st; for (0..($n - 1)) { push @st, sprintf "%i", sin($_ * 90 * 3.141592653 * 2 / 360 / ($n - 1)) * 255 }; print "#define sinsteps $n\nstatic uint8_t sintable[sinsteps] = { "; print join ", ", @st; print " };\n";';
|
|
||||||
// #define sinsteps 16
|
|
||||||
// static uint8_t sintable[sinsteps] = { 0, 26, 53, 78, 103, 127, 149, 170, 189, 206, 220, 232, 242, 249, 253, 255 };
|
|
||||||
|
|
||||||
#define sinsteps 5
|
|
||||||
static uint8_t sintable[sinsteps] = { 0, 97, 180, 235, 255 };
|
|
||||||
|
|
||||||
#define sinstepi (sinsteps - 1)
|
|
||||||
#define sinstepi2 (sinstepi * 2)
|
|
||||||
#define sinstepi3 (sinstepi * 3)
|
|
||||||
#define sinstepi4 (sinstepi * 4)
|
|
||||||
|
|
||||||
int sinstep(uint8_t sequence) {
|
|
||||||
while (sequence >= sinstepi4)
|
|
||||||
sequence -= sinstepi4;
|
|
||||||
if (sequence < (sinstepi + 1))
|
|
||||||
return sintable[sequence];
|
|
||||||
if ((sequence >= (sinstepi + 1)) && (sequence < (sinstepi2 + 1)))
|
|
||||||
return sintable[sinstepi2 - sequence];
|
|
||||||
if ((sequence >= (sinstepi2 + 1)) && (sequence < (sinstepi3 + 1)))
|
|
||||||
return -sintable[sequence - sinstepi2];
|
|
||||||
if ((sequence >= (sinstepi3 + 1)) && (sequence < (sinstepi4 + 1)))
|
|
||||||
return -sintable[sinstepi4 - sequence];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < ((sinstepi * 4) * 3); i++)
|
|
||||||
{
|
|
||||||
printf("%2i: %+4i %+4i\n", i, sinstep(i), sinstep(i + sinstepi));
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue