init
This commit is contained in:
commit
7af260dcea
41
Makefile
Normal file
41
Makefile
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
PRG = rgbyteclock
|
||||||
|
OBJ = rgbyteclock.o timer.o lcd.o main.o
|
||||||
|
MCU_TARGET = atmega16
|
||||||
|
OPTIMIZE = -Os
|
||||||
|
|
||||||
|
DEFS =
|
||||||
|
LIBS =
|
||||||
|
|
||||||
|
CC = avr-gcc
|
||||||
|
|
||||||
|
override CFLAGS = -g -Wall $(OPTIMIZE) -DF_CPU=16000000UL -std=gnu99 -mmcu=$(MCU_TARGET) $(DEFS)
|
||||||
|
override LDFLAGS = -Wl,-Map,$(PRG).map
|
||||||
|
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
SIZE = avr-size -A
|
||||||
|
|
||||||
|
|
||||||
|
all: $(PRG).hex
|
||||||
|
|
||||||
|
$(PRG).elf: $(OBJ)
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
@echo
|
||||||
|
@$(SIZE) $@
|
||||||
|
@echo
|
||||||
|
|
||||||
|
# dependency:
|
||||||
|
rgbyteclock.o: timer.o lcd.o rgbyteclock.h
|
||||||
|
main.o: rgbyteclock.o
|
||||||
|
timer.o:timer.h
|
||||||
|
lcd.o: lcd.h
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak
|
||||||
|
rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)
|
||||||
|
|
||||||
|
hex: $(PRG).hex
|
||||||
|
|
||||||
|
%.hex: %.elf
|
||||||
|
$(OBJCOPY) -j .text -j .data -O ihex $< $@
|
||||||
|
|
203
lcd.c
Normal file
203
lcd.c
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Martin Wenger <martin.wenger@arcormail.de> and Stefan Rupp <struppi@struppi.name>
|
||||||
|
* wrote this file. As long as you retain this notice you can do whatever you want
|
||||||
|
* with this stuff. If we meet some day, and you think this stuff is worth it,
|
||||||
|
* you can buy me/us a beer in return.
|
||||||
|
* (c) 2005-2010 Martin Wenger, Stefan Rupp
|
||||||
|
* (c) 2014 Stefan Rupp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <compat/ina90.h> // ==> _NOP()
|
||||||
|
|
||||||
|
#include "timer.h"
|
||||||
|
#include "lcd.h"
|
||||||
|
|
||||||
|
#define WAIT_250_ns() _NOP()
|
||||||
|
|
||||||
|
#define LCD_DATA_MODE() (PORTC |= (1<<PC4))
|
||||||
|
#define LCD_CMD_MODE() (PORTC &= ~(1<<PC4))
|
||||||
|
|
||||||
|
#define LCD_SET_ENABLE() (PORTC |= (1<<PC5))
|
||||||
|
#define LCD_RESET_ENABLE() (PORTC &= ~(1<<PC5))
|
||||||
|
|
||||||
|
// !!!!!!!
|
||||||
|
#define LCD_SET_READ() DDRC &= ~(0x0f);PORTC &= ~(0x0f);PORTB |= (1<<PB0)
|
||||||
|
#define LCD_SET_WRITE() PORTB &= ~(1<<PB0);DDRC |= 0x0f
|
||||||
|
#define LCD_BUSY_FLAG (0x80)
|
||||||
|
// !!!!!!!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint8_t lcd_read_byte(uint8_t RS)
|
||||||
|
{
|
||||||
|
uint8_t byte;
|
||||||
|
|
||||||
|
if (RS)
|
||||||
|
LCD_DATA_MODE();
|
||||||
|
else
|
||||||
|
LCD_CMD_MODE();
|
||||||
|
|
||||||
|
LCD_SET_READ();
|
||||||
|
|
||||||
|
LCD_SET_ENABLE();
|
||||||
|
WAIT_250_ns();
|
||||||
|
byte = (PINC<<4);
|
||||||
|
LCD_RESET_ENABLE();
|
||||||
|
|
||||||
|
WAIT_250_ns();
|
||||||
|
WAIT_250_ns();
|
||||||
|
|
||||||
|
LCD_SET_ENABLE();
|
||||||
|
WAIT_250_ns();
|
||||||
|
byte |= PINC & 0x0f;
|
||||||
|
LCD_RESET_ENABLE();
|
||||||
|
|
||||||
|
return byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void lcd_wait_while_busy(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t byte;
|
||||||
|
do {
|
||||||
|
byte = lcd_read_byte(0);
|
||||||
|
} while (byte & LCD_BUSY_FLAG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void send_nibble(uint8_t nibble)
|
||||||
|
{
|
||||||
|
LCD_SET_WRITE();
|
||||||
|
PORTC = (PORTC & 0xf0) | (0x0f & nibble);
|
||||||
|
LCD_SET_ENABLE();
|
||||||
|
WAIT_250_ns();
|
||||||
|
LCD_RESET_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send one byte to the LCD
|
||||||
|
* \param byte The byte to send to the LCD
|
||||||
|
* \param RS specifies whether byte sent is data (RS==1) or command (RS==0)
|
||||||
|
*/
|
||||||
|
static inline void lcd_send_byte(uint8_t byte, uint8_t RS)
|
||||||
|
{
|
||||||
|
lcd_wait_while_busy();
|
||||||
|
if (RS)
|
||||||
|
LCD_DATA_MODE();
|
||||||
|
else
|
||||||
|
LCD_CMD_MODE();
|
||||||
|
|
||||||
|
send_nibble(byte >> 4);
|
||||||
|
_NOP();
|
||||||
|
send_nibble(0x0f & byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int lcd_get(void)
|
||||||
|
{
|
||||||
|
lcd_wait_while_busy();
|
||||||
|
return lcd_read_byte(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int lcd_put(char c)
|
||||||
|
{
|
||||||
|
lcd_send_byte(c, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_puts(char *s)
|
||||||
|
{
|
||||||
|
while (*s) {
|
||||||
|
//lcd_put(*s++);
|
||||||
|
lcd_send_byte(*s++, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_cursor(uint8_t blink)
|
||||||
|
{
|
||||||
|
if (blink) {
|
||||||
|
// enable display with cursor + blinking
|
||||||
|
lcd_send_byte(0x0f, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// enable display, no cursor, no blinking
|
||||||
|
lcd_send_byte(0x0c, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_init(void)
|
||||||
|
{
|
||||||
|
/* Initialize both ATmega and Dsiplay
|
||||||
|
* After return from this function,
|
||||||
|
* display we be set to 4-bit data mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
// wait until LCD gets ready to accept instructions.
|
||||||
|
timer_wait(50);
|
||||||
|
|
||||||
|
// set CONTROL Pins as outputs:
|
||||||
|
DDRC = 0x3f;
|
||||||
|
DDRB |= (1<<PB0);
|
||||||
|
|
||||||
|
LCD_CMD_MODE();
|
||||||
|
LCD_SET_WRITE();
|
||||||
|
|
||||||
|
// set LCD to 8-bit mode
|
||||||
|
send_nibble(0x03);
|
||||||
|
|
||||||
|
timer_wait(5);
|
||||||
|
send_nibble(0x03);
|
||||||
|
|
||||||
|
timer_wait(5);
|
||||||
|
send_nibble(0x03);
|
||||||
|
|
||||||
|
// LCD definitely is in 8-bit mode now
|
||||||
|
|
||||||
|
// set module to 4-bit mode now
|
||||||
|
// Remember! As we're in 8-bit mode now,
|
||||||
|
// send_nibble is the right thing, not send_byte!
|
||||||
|
timer_wait(5);
|
||||||
|
send_nibble(0x02);
|
||||||
|
timer_wait(5);
|
||||||
|
|
||||||
|
// set to 5 x 8 dots per character,
|
||||||
|
// 16 characters per line, 2 lines
|
||||||
|
lcd_send_byte(0x28, 0);
|
||||||
|
|
||||||
|
// enable display, no cursor, no blinking
|
||||||
|
//lcd_send_byte(0x0c, 0);
|
||||||
|
// enable display with cursor + blinking
|
||||||
|
//lcd_send_byte(0x0f, 0);
|
||||||
|
lcd_cursor(1);
|
||||||
|
|
||||||
|
// Set display to
|
||||||
|
// + Move cursor (and do not shift display)
|
||||||
|
// + Move right
|
||||||
|
lcd_send_byte(0x04, 0);
|
||||||
|
|
||||||
|
// clear dislay
|
||||||
|
lcd_clear();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_clear(void)
|
||||||
|
{
|
||||||
|
lcd_send_byte(0x01, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_locate(uint8_t row, uint8_t col)
|
||||||
|
{
|
||||||
|
if (row)
|
||||||
|
col += 0x40;
|
||||||
|
lcd_send_byte(0x80 + col, 0);
|
||||||
|
}
|
14
lcd.h
Normal file
14
lcd.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#if !defined __LCD_H
|
||||||
|
#define __LCD_H
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
void lcd_init(void);
|
||||||
|
int lcd_put(char c);
|
||||||
|
void lcd_puts(char *s);
|
||||||
|
int lcd_get(void);
|
||||||
|
void lcd_clear(void);
|
||||||
|
void lcd_locate(uint8_t row, uint8_t column);
|
||||||
|
void lcd_cursor(uint8_t blink);
|
||||||
|
|
||||||
|
#endif
|
19
main.c
Normal file
19
main.c
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include "timer.h"
|
||||||
|
#include "lcd.h"
|
||||||
|
#include "rgbyteclock.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
timer_init();
|
||||||
|
lcd_init();
|
||||||
|
|
||||||
|
rgbyteclock();
|
||||||
|
// rgbyteclock() should never end, but who knows...
|
||||||
|
while (1) { ; }
|
||||||
|
|
||||||
|
}
|
15
rgbyteclock.c
Normal file
15
rgbyteclock.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#include "rgbyteclock.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void rgbyteclock(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
15
rgbyteclock.h
Normal file
15
rgbyteclock.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
#ifndef RGBYTECLOCK_H
|
||||||
|
#define RGBYTECLOCK_H
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include "timer.h"
|
||||||
|
#include "lcd.h"
|
||||||
|
|
||||||
|
|
||||||
|
void rgbyteclock(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // RGBYTECLOCK_H
|
||||||
|
|
163
timer.c
Normal file
163
timer.c
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Martin Wenger <martin.wenger@arcormail.de> and Stefan Rupp <struppi@struppi.name>
|
||||||
|
* wrote this file. As long as you retain this notice you can do whatever you want
|
||||||
|
* with this stuff. If we meet some day, and you think this stuff is worth it,
|
||||||
|
* you can buy me/us a beer in return.
|
||||||
|
* (c) 2005-2010 Martin Wenger, Stefan Rupp
|
||||||
|
* (c) 2013,2014 Stefan Rupp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include "timer.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* timer_time gets increased on every interrupt
|
||||||
|
* those interrupts happen every 1ms
|
||||||
|
*/
|
||||||
|
static volatile uint32_t timer_time;
|
||||||
|
|
||||||
|
ISR(TIMER0_COMP_vect) {
|
||||||
|
++timer_time;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the timer
|
||||||
|
* This function has to be called first, before calling timer_wait and/or timer_get,
|
||||||
|
* else timer_get will always return 0, and timer_wait will wait forever!
|
||||||
|
*/
|
||||||
|
|
||||||
|
void timer_init(void)
|
||||||
|
{
|
||||||
|
// Stop all interrupts
|
||||||
|
cli();
|
||||||
|
|
||||||
|
// Reset timer to zero
|
||||||
|
timer_time = 0;
|
||||||
|
|
||||||
|
// - Time accuracy: 1 millisecond (corresponding frequency: 1kHz)
|
||||||
|
// ==> F_CPU = 2Mhz
|
||||||
|
// ==> 16Mhz / 64 = 250 kHz
|
||||||
|
// ==> let timer count to 250 to get 1kHz frequency
|
||||||
|
// therefore:
|
||||||
|
// - Set Timer/Counter0 prescaler to 64 ==> (1<<CS01)|(1<<CS00)
|
||||||
|
// - Set OCR2 to 249
|
||||||
|
// - CTC ( i.e. clear counter, when COUNTER == OCR0A) ==> (1<<WGM01)
|
||||||
|
OCR0 = 249;
|
||||||
|
TCCR0 = (1<<CS01)|(1<<CS00)|(1<<WGM01);
|
||||||
|
|
||||||
|
// Interrupts setzen
|
||||||
|
TIMSK |= (1<<OCIE0);
|
||||||
|
|
||||||
|
// Allow interrupts
|
||||||
|
sei();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current time
|
||||||
|
* \return the current time (in ms)
|
||||||
|
*/
|
||||||
|
inline uint32_t timer_get(void)
|
||||||
|
{
|
||||||
|
uint32_t t;
|
||||||
|
uint8_t sreg;
|
||||||
|
|
||||||
|
sreg = SREG;
|
||||||
|
cli();
|
||||||
|
t = timer_time;
|
||||||
|
SREG = sreg;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for (at least) the specified amount of time
|
||||||
|
* \param delay The time to wait (in ms)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void timer_wait(uint32_t delay)
|
||||||
|
{
|
||||||
|
uint32_t end = timer_get() + delay +1;
|
||||||
|
while ( end > timer_get() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a integer timestamp (in microseconds)
|
||||||
|
* into hours, minutes, seconds, microseconds
|
||||||
|
* \param time the time in microseconds
|
||||||
|
* \param hours will be filled in to contain the hours after return
|
||||||
|
* \param minutes will be filled in to contain the minutes after return
|
||||||
|
* \param seconds will be filled in to contain the seconds after return
|
||||||
|
* \param ms be filled in to contain the microseconds after return
|
||||||
|
*/
|
||||||
|
void timer_decode(uint32_t time, uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint16_t *ms)
|
||||||
|
{
|
||||||
|
if (ms != NULL) {
|
||||||
|
*ms = time % 1000;
|
||||||
|
}
|
||||||
|
time /= 1000;
|
||||||
|
if (seconds != NULL) {
|
||||||
|
*seconds = time % 60;
|
||||||
|
}
|
||||||
|
time /= 60;
|
||||||
|
if (minutes != NULL) {
|
||||||
|
*minutes = time % 60;
|
||||||
|
}
|
||||||
|
time /= 60;
|
||||||
|
if (hours != NULL) {
|
||||||
|
*hours = time;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a time given as hours, minutes, seconds and microsecods into a integer storing micorseconds
|
||||||
|
* \param time the variable to store the time into
|
||||||
|
* \param hour the hours to store
|
||||||
|
* \param hour the minutes to store
|
||||||
|
* \param hour the seconds to store
|
||||||
|
* \param hour the microseconds to store
|
||||||
|
*/
|
||||||
|
void timer_encode(uint32_t *time, uint8_t hours, uint8_t minutes, uint8_t seconds, uint16_t ms)
|
||||||
|
{
|
||||||
|
|
||||||
|
*time = hours;
|
||||||
|
*time *= 60;
|
||||||
|
|
||||||
|
*time += minutes;
|
||||||
|
*time *= 60;
|
||||||
|
|
||||||
|
*time += seconds;
|
||||||
|
*time *= 1000U;
|
||||||
|
|
||||||
|
*time += ms;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void timer_validate(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint16_t *ms)
|
||||||
|
{
|
||||||
|
|
||||||
|
while (*ms >= 1000) {
|
||||||
|
*ms -= 1000;
|
||||||
|
(*seconds)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*seconds >= 60) {
|
||||||
|
*ms -= 60;
|
||||||
|
(*minutes)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*minutes >= 60) {
|
||||||
|
*minutes -= 60;
|
||||||
|
(*hours)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
12
timer.h
Normal file
12
timer.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#if !defined __TIMER_H
|
||||||
|
#define __TIMER_H
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
void timer_wait(uint32_t delay);
|
||||||
|
uint32_t timer_get(void);
|
||||||
|
void timer_init(void);
|
||||||
|
void timer_decode(uint32_t time, uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint16_t *ms);
|
||||||
|
void timer_encode(uint32_t *time, uint8_t hour, uint8_t minute, uint8_t seconds, uint16_t ms);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user