avr_firmware: Add prelim. ATmega32 platform; add LCD support
This commit is contained in:
@@ -1,12 +1,17 @@
|
||||
CC=avr-gcc
|
||||
CCOPTS=-mmcu=atmega164a -std=c11 -flto -Os -ggdb -Wall -Wextra -pedantic -DF_CPU=8000000UL
|
||||
#CCOPTS=-mmcu=atmega164a -std=c11 -flto -Os -ggdb -Wall -Wextra -pedantic -DF_CPU=8000000UL
|
||||
CCOPTS=-mmcu=atmega32 -std=c11 -flto -Os -ggdb -Wall -Wextra -pedantic -DF_CPU=8000000UL
|
||||
|
||||
CCSRCS ::= uart.c main.c modem.c timer.c
|
||||
CCSRCS ::= uart.c main.c modem.c timer.c lcd.c
|
||||
|
||||
all: fw.elf
|
||||
|
||||
prog: fw.elf
|
||||
sudo avrdude -c avrisp2 -p m32 -U flash:w:$<
|
||||
|
||||
fw.elf: $(addprefix objs/,$(CCSRCS:.c=.o))
|
||||
$(CC) $(CCOPTS) -o $@ $^
|
||||
@size $@
|
||||
|
||||
objs/%.o: src/%.c
|
||||
$(CC) $(CCOPTS) -c -MMD -MP -o $@ $<
|
||||
@@ -18,3 +23,5 @@ clean:
|
||||
$(addprefix objs/,$(CCSRCS:.c=.P))
|
||||
|
||||
-include $(addprefix objs/,$(CCSRCS:.c=.P))
|
||||
|
||||
.PHONY: clean all prog
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
|
||||
#define LCD_DPORT PORTC
|
||||
#define LCD_DDDR DDRC
|
||||
#define LCD_DPIN PINC
|
||||
|
||||
#define LCD_CPORT PORTA
|
||||
#define LCD_CDDR DDRA
|
||||
#define LCD_RS 0
|
||||
#define LCD_RW 1
|
||||
#define LCD_EN 2
|
||||
|
||||
#define UART0_CTS_PORT PIND
|
||||
#define UART0_RTS_PORT PIND
|
||||
#define UART0_CTS 5
|
||||
|
||||
98
avr_firmware/src/lcd.c
Normal file
98
avr_firmware/src/lcd.c
Normal file
@@ -0,0 +1,98 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "lcd.h"
|
||||
|
||||
#define LCD_CMASK ((_BV(LCD_RS) | _BV(LCD_RW) | (_BV(LCD_EN))))
|
||||
|
||||
uint8_t _lcdRead(bool rs)
|
||||
{
|
||||
LCD_CPORT = (LCD_CPORT & ~LCD_CMASK) | _BV(LCD_RW) | (rs?_BV(LCD_RS):0);
|
||||
|
||||
LCD_DDDR = 0x00;
|
||||
|
||||
LCD_CPORT |= _BV(LCD_EN);
|
||||
|
||||
_delay_us(0.32);
|
||||
|
||||
uint8_t ret = LCD_DPIN;
|
||||
|
||||
LCD_CPORT &= ~_BV(LCD_EN);
|
||||
|
||||
_delay_us(0.06);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _lcdWrite(bool rs, uint8_t data)
|
||||
{
|
||||
LCD_CPORT = (LCD_CPORT & ~LCD_CMASK) | (rs?_BV(LCD_RS):0);
|
||||
|
||||
LCD_DDDR = 0xff;
|
||||
LCD_DPORT = data;
|
||||
|
||||
LCD_CPORT |= _BV(LCD_EN);
|
||||
|
||||
_delay_us(0.45);
|
||||
|
||||
LCD_CPORT &= ~_BV(LCD_EN);
|
||||
}
|
||||
|
||||
void _lcdBusyWait()
|
||||
{
|
||||
while (_lcdRead(false) & _BV(7));
|
||||
}
|
||||
|
||||
uint8_t lcdRead(bool rs)
|
||||
{
|
||||
_lcdBusyWait();
|
||||
|
||||
return _lcdRead(rs);
|
||||
}
|
||||
|
||||
void lcdWrite(bool rs, uint8_t data)
|
||||
{
|
||||
_lcdBusyWait();
|
||||
|
||||
_lcdWrite(rs, data);
|
||||
}
|
||||
|
||||
void lcdWriteStr(char const* str)
|
||||
{
|
||||
while (*str != '\0')
|
||||
lcdWrite(true, (uint8_t)*str++);
|
||||
}
|
||||
|
||||
void lcdWriteStrP(char const* str)
|
||||
{
|
||||
char c;
|
||||
while ((c = pgm_read_byte(str++)) != '\0')
|
||||
lcdWrite(true, (uint8_t)c);
|
||||
}
|
||||
|
||||
static const uint8_t lineLUT[4] PROGMEM = {0x00, 0x40, 0x14, 0x54};
|
||||
|
||||
void lcdSetPos(unsigned x, unsigned y)
|
||||
{
|
||||
const uint8_t adr = pgm_read_byte(&lineLUT[y]) + x;
|
||||
lcdWrite(false, 0x80 | adr);
|
||||
}
|
||||
|
||||
int lcdInit()
|
||||
{
|
||||
LCD_DDDR = 0x00;
|
||||
LCD_CDDR |= LCD_CMASK;
|
||||
|
||||
lcdWrite(false, 0x38);
|
||||
lcdWrite(false, 0x0c);
|
||||
lcdWrite(false, 0x01);
|
||||
lcdWrite(false, 0x06);
|
||||
|
||||
lcdWrite(false, 0x80);
|
||||
|
||||
return 0;
|
||||
}
|
||||
11
avr_firmware/src/lcd.h
Normal file
11
avr_firmware/src/lcd.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef DMXGSM_AVR_LCD_H
|
||||
#define DMXGSM_AVR_LCD_H
|
||||
|
||||
int lcdInit();
|
||||
|
||||
void lcdWriteStr(char const* str);
|
||||
void lcdWriteStrP(char const* str);
|
||||
|
||||
void lcdSetPos(unsigned x, unsigned y);
|
||||
|
||||
#endif
|
||||
@@ -1,16 +1,54 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#include "timer.h"
|
||||
#include "modem.h"
|
||||
#include "uart.h"
|
||||
#include "lcd.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
const unsigned char osccal = eeprom_read_byte(0);
|
||||
OSCCAL = osccal;
|
||||
|
||||
DDRD = 1<<7;
|
||||
|
||||
timerInit();
|
||||
uart0Init();
|
||||
|
||||
sei();
|
||||
|
||||
lcdInit();
|
||||
uart0Init();
|
||||
|
||||
lcdWriteStrP(PSTR("Hallo, Welt!"));
|
||||
|
||||
lcdSetPos(0, 1);
|
||||
|
||||
char buf[6];
|
||||
utoa(osccal, buf, 16);
|
||||
|
||||
lcdWriteStrP(PSTR("OSCCAL = 0x"));
|
||||
lcdWriteStr(buf);
|
||||
|
||||
unsigned oldSeconds = 0;
|
||||
while (true) {
|
||||
sleep_mode();
|
||||
|
||||
unsigned seconds = timerGetSeconds();
|
||||
if (seconds != oldSeconds) {
|
||||
utoa(seconds, buf, 10);
|
||||
lcdSetPos(0,2);
|
||||
lcdWriteStr(buf);
|
||||
oldSeconds = seconds;
|
||||
}
|
||||
}
|
||||
|
||||
modemInit();
|
||||
|
||||
//modemInit();
|
||||
//xmitPPP("TEST", 4);
|
||||
}
|
||||
|
||||
@@ -3,15 +3,25 @@
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
volatile unsigned timerTicks;
|
||||
volatile unsigned timerTicks, timerSeconds;
|
||||
|
||||
ISR(TIMER0_OVF_vect, ISR_NOBLOCK)
|
||||
ISR(TIMER1_COMPA_vect, ISR_NOBLOCK)
|
||||
{
|
||||
static unsigned ledTicks = 0;
|
||||
|
||||
++timerTicks;
|
||||
|
||||
if (ledTicks >= 24) {
|
||||
PORTD ^= (1<<7);
|
||||
ledTicks = 0;
|
||||
++timerSeconds;
|
||||
} else
|
||||
++ledTicks;
|
||||
}
|
||||
|
||||
int timerInit()
|
||||
{
|
||||
#ifndef __AVR_ATmega32__
|
||||
TCCR0A = 0; // CTC mode
|
||||
TCCR0B = _BV(CS02) | _BV(CS00); // CTC mode, /1024 clk
|
||||
|
||||
@@ -19,7 +29,16 @@ int timerInit()
|
||||
timerTicks = 0u;
|
||||
|
||||
TIMSK0 = _BV(TOIE0);
|
||||
#else
|
||||
TCCR1A = 0;
|
||||
TCCR1B = _BV(WGM12) | _BV(CS02); // CTC mode, /256 clk
|
||||
OCR1AH = 0x02;
|
||||
OCR1AL = 0x70; // 50 Hz timer ticks
|
||||
|
||||
timerTicks = 0u;
|
||||
timerSeconds = 0u;
|
||||
TIMSK = _BV(OCIE1A);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,3 +46,8 @@ unsigned timerGetTicks()
|
||||
{
|
||||
return timerTicks;
|
||||
}
|
||||
|
||||
unsigned timerGetSeconds()
|
||||
{
|
||||
return timerSeconds>>1;
|
||||
}
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
int timerInit();
|
||||
|
||||
unsigned timerGetTicks();
|
||||
unsigned timerGetSeconds();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,22 @@
|
||||
static volatile unsigned char _uart0RXbuf[UART_RXBUF_SIZE];
|
||||
static volatile size_t _uart0RXwr, _uart0RXrd;
|
||||
|
||||
#ifdef __AVR_ATmega32__
|
||||
#define USART0_RX_vect USART_RXC_vect
|
||||
#define UDR0 UDR
|
||||
#define UBRR0H UBRRH
|
||||
#define UBRR0L UBRRL
|
||||
#define UCSR0A UCSRA
|
||||
#define UCSR0B UCSRB
|
||||
#define UCSR0C UCSRC
|
||||
#define RXCIE0 RXCIE
|
||||
#define RXEN0 RXEN
|
||||
#define TXEN0 TXEN
|
||||
#define UCSZ01 UCSZ1
|
||||
#define UCSZ00 UCSZ0
|
||||
#define UDRE0 UDRE
|
||||
#endif
|
||||
|
||||
ISR(USART0_RX_vect)
|
||||
{
|
||||
_uart0RXbuf[_uart0RXwr++] = UDR0;
|
||||
@@ -26,23 +42,27 @@ void uart0Init()
|
||||
UBRR0L = 12; // 38400 baud
|
||||
|
||||
UCSR0A = 0;
|
||||
UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
|
||||
UCSR0B = _BV(RXEN0) | _BV(TXEN0);
|
||||
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); // 8 bit, 1 stop, no parity
|
||||
|
||||
_uart0RXwr = 0;
|
||||
_uart0RXrd = UART_RXBUF_SIZE-1;
|
||||
|
||||
UCSR0B |= _BV(RXCIE0);
|
||||
|
||||
UART0_RTS_PORT |= _BV(UART0_RTS);
|
||||
}
|
||||
|
||||
void uart1Init()
|
||||
{
|
||||
#ifndef __AVR_ATmega32__
|
||||
UBRR1H = 0;
|
||||
UBRR1L = 1; // 250k baud
|
||||
|
||||
UCSR1A = 0;
|
||||
UCSR1B = _BV(UDRIE1) | _BV(TXEN1);
|
||||
UCSR1C = _BV(USBS1) | _BV(UCSZ01) | _BV(UCSZ00); // 8 bit, 2 stop, no parity
|
||||
#endif
|
||||
}
|
||||
|
||||
void uart0Xmit(unsigned char data)
|
||||
|
||||
Reference in New Issue
Block a user