tixiv
16 years ago
commit
fe14b29d15
106 changed files with 16442 additions and 0 deletions
@ -0,0 +1,173 @@ |
|||
TARGET := image |
|||
TOPDIR = . |
|||
|
|||
SRC = \
|
|||
main.c \
|
|||
eeprom_reserve.c \
|
|||
pixel.c \
|
|||
util.c \
|
|||
|
|||
|
|||
LAUNCH_BOOTLOADER = launch-bootloader |
|||
SERIAL = /dev/ttyUSB0 |
|||
|
|||
export TOPDIR |
|||
##############################################################################
|
|||
all: compile-$(TARGET) |
|||
@echo "===============================" |
|||
@echo "$(TARGET) compiled for: $(MCU)" |
|||
@echo "size is: " |
|||
@${TOPDIR}/scripts/size $(TARGET) |
|||
@echo "===============================" |
|||
|
|||
|
|||
##############################################################################
|
|||
# generic fluff
|
|||
include defaults.mk |
|||
#include $(TOPDIR)/rules.mk
|
|||
|
|||
##############################################################################
|
|||
# generate SUBDIRS variable
|
|||
#
|
|||
|
|||
.subdirs: autoconf.h |
|||
$(RM) -f $@ |
|||
echo "SUBDIRS += borg_hw" >> $@ |
|||
echo "SUBDIRS += animations" >> $@ |
|||
(for subdir in `grep -e "^#define .*_SUPPORT" autoconf.h \
|
|||
| sed -e "s/^#define //" -e "s/_SUPPORT.*//" \
|
|||
| tr "[A-Z]\\n" "[a-z] " `; do \
|
|||
test -d $$subdir && echo "SUBDIRS += $$subdir" ; \
|
|||
done) | sort -u >> $@ |
|||
|
|||
ifneq ($(no_deps),t) |
|||
ifneq ($(MAKECMDGOALS),clean) |
|||
ifneq ($(MAKECMDGOALS),mrproper) |
|||
ifneq ($(MAKECMDGOALS),menuconfig) |
|||
|
|||
include $(TOPDIR)/.subdirs |
|||
include $(TOPDIR)/.config |
|||
|
|||
endif # MAKECMDGOALS!=menuconfig
|
|||
endif # MAKECMDGOALS!=mrproper
|
|||
endif # MAKECMDGOALS!=clean
|
|||
endif # no_deps!=t
|
|||
|
|||
##############################################################################
|
|||
|
|||
.PHONY: compile-subdirs |
|||
compile-subdirs: |
|||
for dir in $(SUBDIRS); do make -C $$dir lib$$dir.a || exit 5; done |
|||
|
|||
.PHONY: compile-$(TARGET) |
|||
compile-$(TARGET): compile-subdirs $(TARGET).hex $(TARGET).bin $(TARGET).lst |
|||
|
|||
OBJECTS += $(patsubst %.c,%.o,${SRC}) |
|||
LINKLIBS = $(foreach subdir,$(SUBDIRS),$(subdir)/lib$(subdir).a) |
|||
|
|||
# FIXME how can we omit specifying every file to be linked twice?
|
|||
# This is currently necessary because of interdependencies between
|
|||
# the libraries, which aren't denoted in these however.
|
|||
$(TARGET): $(OBJECTS) $(LINKLIBS) |
|||
$(CC) $(LDFLAGS) -o $@ $(OBJECTS) \
|
|||
$(foreach subdir,$(SUBDIRS),-L$(subdir) -l$(subdir)) \
|
|||
$(foreach subdir,$(SUBDIRS),-l$(subdir)) \
|
|||
$(foreach subdir,$(SUBDIRS),-l$(subdir)) |
|||
|
|||
|
|||
##############################################################################
|
|||
|
|||
%.hex: % |
|||
$(OBJCOPY) -O ihex -R .eeprom $< $@ |
|||
|
|||
ifeq ($(HTTPD_INLINE_FILES_SUPPORT),y) |
|||
INLINE_FILES := $(wildcard httpd/embed/*) |
|||
else |
|||
INLINE_FILES := |
|||
endif |
|||
|
|||
%.bin: % $(INLINE_FILES) |
|||
$(OBJCOPY) -O binary -R .eeprom $< $@ |
|||
ifeq ($(HTTPD_INLINE_FILES_SUPPORT),y) |
|||
$(MAKE) -C httpd httpd-concat |
|||
httpd/do-embed $(INLINE_FILES) |
|||
$(OBJCOPY) -O ihex -I binary $(TARGET).bin $(TARGET).hex |
|||
endif |
|||
|
|||
%.eep.hex: % |
|||
$(OBJCOPY) --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex -j .eeprom $< $@ |
|||
|
|||
%.lst: % |
|||
$(OBJDUMP) -h -S $< > $@ |
|||
|
|||
%-size: %.hex |
|||
$(SIZE) $< |
|||
|
|||
##############################################################################
|
|||
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
|
|||
else if [ -x /bin/bash ]; then echo /bin/bash; \
|
|||
else echo sh; fi ; fi) |
|||
|
|||
menuconfig: |
|||
$(MAKE) -C scripts/lxdialog all |
|||
$(CONFIG_SHELL) scripts/Menuconfig config.in |
|||
test -e .config |
|||
@$(MAKE) no_deps=t what-now-msg |
|||
|
|||
what-now-msg: |
|||
@echo "" |
|||
@echo "Next, you can: " |
|||
@echo " * 'make' to compile your borgware" |
|||
@for subdir in $(SUBDIRS); do \
|
|||
test -e "$$subdir/configure" -a -e "$$subdir/cfgpp" \
|
|||
&& echo " * 'make $$subdir/menuconfig' to" \
|
|||
"further configure $$subdir"; done || true |
|||
@echo "" |
|||
.PHONY: what-now-msg |
|||
|
|||
%/menuconfig: |
|||
$(SH) "$(@D)/configure" |
|||
@$(MAKE) what-now-msg |
|||
|
|||
##############################################################################
|
|||
clean: |
|||
$(MAKE) -f rules.mk no_deps=t clean-common |
|||
$(RM) $(TARGET) $(TARGET).bin $(TARGET).hex .subdirs |
|||
for subdir in `find . -type d`; do \
|
|||
test "x$$subdir" != "x." \
|
|||
&& test -e $$subdir/Makefile \
|
|||
&& make no_deps=t -C $$subdir clean; done |
|||
|
|||
mrproper: |
|||
$(MAKE) clean |
|||
$(RM) -f autoconf.h .config config.mk .menuconfig.log .config.old |
|||
|
|||
sflash: $(TARGET).hex |
|||
$(LAUNCH_BOOTLOADER) $(SERIAL) 115200 |
|||
avrdude -p m32 -b 115200 -u -c avr109 -P $(SERIAL) -U f:w:$< -F |
|||
echo X > $(SERIAL) |
|||
|
|||
|
|||
.PHONY: clean mrproper sflash |
|||
##############################################################################
|
|||
# configure ethersex
|
|||
#
|
|||
show-config: autoconf.h |
|||
@echo |
|||
@echo "These modules are currently enabled: " |
|||
@echo "======================================" |
|||
@grep -e "^#define .*_SUPPORT" autoconf.h | sed -e "s/^#define / * /" -e "s/_SUPPORT.*//" |
|||
|
|||
.PHONY: show-config |
|||
|
|||
autoconf.h .config: |
|||
@echo make\'s goal: $(MAKECMDGOALS) |
|||
ifneq ($(MAKECMDGOALS),menuconfig) |
|||
# make sure menuconfig isn't called twice, on `make menuconfig' |
|||
test -s autoconf.h -a -s .config || $(MAKE) no_deps=t menuconfig |
|||
# test the target file, test fails if it doesn't exist |
|||
# and will keep make from looping menuconfig. |
|||
test -s autoconf.h -a -s .config |
|||
endif |
|||
|
|||
include depend.mk |
@ -0,0 +1,32 @@ |
|||
|
|||
OBJ = borg_hw.o main.o util.o pixel.o programm.o borg_can.o can.o \ |
|||
spi.o scrolltext3.o font_arial8.o joystick.o snake.o \ |
|||
eeprom_reserve.o persistentCounter.o prng.o matrix.o \ |
|||
invader_draw.o invader_init.o invader_proc.o invaders2.o \ |
|||
tetris/tetris.o menu.o gameoflife.o memxor.o noekeon_asm.o \ |
|||
mcuf.o uart.o |
|||
|
|||
CANADDR = 0x43 |
|||
|
|||
SERIAL = /dev/ttyUSB0 |
|||
|
|||
include ../../make/avr.mk |
|||
|
|||
.PHONY: tetris/tetris.o |
|||
tetris/tetris.o: |
|||
$(MAKE) "MCU_CC=$(MCU_CC)" "MCU_LD=$(MCU_LD)" "LDFLAGS=$(LDFLAGS)" \ |
|||
"CFLAGS=$(CFLAGS) -DNDEBUG -pedantic -std=c99" --directory=tetris |
|||
|
|||
LAUNCH_BOOTLOADER = launch-bootloader |
|||
|
|||
sflash: $(OUT).hex |
|||
$(LAUNCH_BOOTLOADER) $(SERIAL) 115200 |
|||
avrdude -p m32 -b 115200 -u -c avr109 -P $(SERIAL) -U f:w:$(OUT).hex -F |
|||
echo X > $(SERIAL) |
|||
|
|||
urflash: image_with_bootloader.hex |
|||
avrdude -p m32 -c bsd -P /dev/parport0 -U hfuse:w:0xdc:m |
|||
avrdude -p m32 -c bsd -P /dev/parport0 -U lfuse:w:0xef:m |
|||
avrdude -p m32 -c bsd -P /dev/parport0 -U f:w:image_with_bootloader.hex |
|||
avrdude -p m32 -c bsd -P /dev/parport0 -U e:w:image_eeprom.hex |
|||
avrdude -p m32 -c bsd -P /dev/parport0 -U lock:w:0x2f:m |
@ -0,0 +1,2 @@ |
|||
Source für Borg16 Controller |
|||
|
@ -0,0 +1,5 @@ |
|||
|
|||
Hier liegt der Versuch, eine universelle Codebasis für 2d-borgs zu bauen, die |
|||
durch 'make menuconfig' konfigurierbar ist. Das ganze ist grade nochnicht |
|||
besonders weit, und funktioniert noch garnicht. Work is in progress... |
|||
|
@ -0,0 +1,21 @@ |
|||
TARGET = libanimations.a |
|||
TOPDIR = .. |
|||
|
|||
include $(TOPDIR)/defaults.mk |
|||
|
|||
SRC = programm.c |
|||
|
|||
ifeq ($(ANIMATION_SNAKE),y) |
|||
SRC += snake.c |
|||
endif |
|||
|
|||
ifeq ($(ANIMATION_MATRIX),y) |
|||
SRC += matrix.c |
|||
endif |
|||
|
|||
ifeq ($(ANIMATION_GAMEOFLIFE),y) |
|||
SRC += gameoflife.c |
|||
endif |
|||
|
|||
|
|||
include $(TOPDIR)/rules.mk |
@ -0,0 +1,312 @@ |
|||
/**
|
|||
* Conways Game of life |
|||
* Author: Daniel Otte |
|||
* License: GPLv3 |
|||
* |
|||
* |
|||
*/ |
|||
|
|||
#include <stdint.h> |
|||
#include <util/delay.h> |
|||
#include <avr/sfr_defs.h> /* for debugging */ |
|||
#include "../config.h" |
|||
#include "../random/prng.h" |
|||
#include "../pixel.h" |
|||
#include "../util.h" |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
#undef DEBUG |
|||
|
|||
#define XSIZE NUM_COLS |
|||
#define YSIZE NUM_ROWS |
|||
|
|||
/*
|
|||
* last line is for debug information |
|||
*/ |
|||
#ifdef DEBUG |
|||
#undef YSIZE |
|||
#define YSIZE (NUM_ROWS-1) |
|||
#define DEBUG_ROW (NUM_ROWS-1) |
|||
#define DEBUG_BIT(pos, val) \ |
|||
setpixel((pixel){(pos)%XSIZE,DEBUG_ROW+(pos)/XSIZE},(val)?3:0) |
|||
#define DEBUG_BYTE(s,v) \ |
|||
DEBUG_BIT((s)*8+0, (v)&(1<<0)); \ |
|||
DEBUG_BIT((s)*8+1, (v)&(1<<1)); \ |
|||
DEBUG_BIT((s)*8+2, (v)&(1<<2)); \ |
|||
DEBUG_BIT((s)*8+3, (v)&(1<<3)); \ |
|||
DEBUG_BIT((s)*8+4, (v)&(1<<4)); \ |
|||
DEBUG_BIT((s)*8+5, (v)&(1<<5)); \ |
|||
DEBUG_BIT((s)*8+6, (v)&(1<<6)); \ |
|||
DEBUG_BIT((s)*8+7, (v)&(1<<7)) |
|||
#else |
|||
#define DEBUG_BIT(s,v) |
|||
#define DEBUG_BYTE(s,v) |
|||
#endif |
|||
|
|||
//#define GLIDER_TEST
|
|||
|
|||
#define BITSTUFFED |
|||
#define LOOP_DETECT_BUFFER_SIZE 8 |
|||
|
|||
#ifndef GOL_DELAY |
|||
#define GOL_DELAY 1 /* milliseconds */ |
|||
#endif |
|||
|
|||
#ifndef GOL_CYCLES |
|||
#define GOL_CYCLES (2*60*3) |
|||
#endif |
|||
|
|||
/******************************************************************************/ |
|||
/******************************************************************************/ |
|||
|
|||
typedef enum{dead=0, alive=1} cell_t; |
|||
|
|||
#ifndef BITSTUFFED |
|||
|
|||
#define FIELD_XSIZE XSIZE |
|||
#define FIELD_YSIZE YSIZE |
|||
|
|||
typedef cell_t field_t[FIELD_XSIZE][FIELD_YSIZE]; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
void setcell(field_t pf, int x, int y, cell_t value){ |
|||
pf[(x+FIELD_XSIZE)%FIELD_XSIZE][(y+FIELD_YSIZE)%FIELD_YSIZE] = value; |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
cell_t getcell(field_t pf, int x, int y){ |
|||
return pf[(x+FIELD_XSIZE)%FIELD_XSIZE][(y+FIELD_YSIZE)%FIELD_YSIZE]; |
|||
} |
|||
|
|||
#else /* BITSTUFFED */ |
|||
|
|||
#define FIELD_XSIZE ((XSIZE+7)/8) |
|||
#define FIELD_YSIZE YSIZE |
|||
|
|||
typedef uint8_t field_t[FIELD_XSIZE][FIELD_YSIZE]; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
void setcell(field_t pf, int x, int y, cell_t value){ |
|||
uint8_t t; |
|||
x = (x+XSIZE) % XSIZE; |
|||
y = (y+YSIZE) % YSIZE; |
|||
|
|||
t = pf[x/8][y]; |
|||
if(value==alive){ |
|||
t |= 1<<(x&7); |
|||
} else { |
|||
t &= ~(1<<(x&7)); |
|||
} |
|||
pf[x/8][y] = t; |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
cell_t getcell(field_t pf, int x, int y){ |
|||
x = (x+XSIZE) % XSIZE; |
|||
y = (y+YSIZE) % YSIZE; |
|||
|
|||
return ((pf[x/8][y])&(1<<(x&7)))?alive:dead; |
|||
} |
|||
#endif |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
uint8_t countsurroundingalive(field_t pf, int x, int y){ |
|||
uint8_t ret=0; |
|||
ret += (getcell(pf, x-1, y-1)==alive)?1:0; |
|||
ret += (getcell(pf, x , y-1)==alive)?1:0; |
|||
ret += (getcell(pf, x+1, y-1)==alive)?1:0; |
|||
|
|||
ret += (getcell(pf, x-1, y )==alive)?1:0; |
|||
ret += (getcell(pf, x+1, y )==alive)?1:0; |
|||
|
|||
ret += (getcell(pf, x-1, y+1)==alive)?1:0; |
|||
ret += (getcell(pf, x , y+1)==alive)?1:0; |
|||
ret += (getcell(pf, x+1, y+1)==alive)?1:0; |
|||
return ret; |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
void nextiteration(field_t dest, field_t src){ |
|||
int x,y; |
|||
uint8_t tc; |
|||
for(y=0; y<YSIZE; ++y){ |
|||
for(x=0; x<XSIZE; ++x){ |
|||
tc=countsurroundingalive(src,x,y); |
|||
switch(tc){ |
|||
// case 0:
|
|||
// case 1:
|
|||
// /* dead */
|
|||
// setcell(dest, x,y, dead);
|
|||
case 2: |
|||
/* keep */ |
|||
setcell(dest, x,y, getcell(src,x,y)); |
|||
break; |
|||
case 3: |
|||
/* alive */ |
|||
setcell(dest, x,y, alive); |
|||
break; |
|||
default: |
|||
/* dead */ |
|||
setcell(dest, x,y, dead); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
void printpf(field_t pf){ |
|||
int x,y; |
|||
for(y=0; y<YSIZE; ++y){ |
|||
for(x=0; x<XSIZE; ++x){ |
|||
setpixel((pixel){x,y},(getcell(pf,x,y)==alive)?3:0); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
void pfcopy(field_t dest, field_t src){ |
|||
int x,y; |
|||
for(y=0; y<YSIZE; ++y){ |
|||
for(x=0; x<XSIZE; ++x){ |
|||
setcell(dest,x,y,getcell(src,x,y)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
#ifndef BITSTUFFED |
|||
uint8_t pfcmp(field_t dest, field_t src){ |
|||
int x,y; |
|||
for(y=0; y<YSIZE; ++y){ |
|||
for(x=0; x<XSIZE; ++x){ |
|||
if (getcell(src,x,y) != getcell(dest,x,y)) |
|||
return 1; |
|||
} |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
uint8 pfempty(field_t src){ int x,y; |
|||
for(y=0; y<YSIZE; ++y){ |
|||
for(x=0; x<XSIZE; ++x){ |
|||
if (getcell(src,x,y)==alive) |
|||
return 0; |
|||
} |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
#else |
|||
|
|||
uint8_t pfcmp(field_t dest, field_t src){ |
|||
int x,y; |
|||
for(y=0; y<FIELD_YSIZE; ++y){ |
|||
for(x=0; x<FIELD_XSIZE; ++x){ |
|||
if (src[x][y] != dest[x][y]) |
|||
return 1; |
|||
} |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
uint8_t pfempty(field_t src){ |
|||
int x,y; |
|||
for(y=0; y<FIELD_YSIZE; ++y){ |
|||
for(x=0; x<FIELD_XSIZE; ++x){ |
|||
if (src[x][y]!=0) |
|||
return 0; |
|||
} |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
#endif |
|||
/******************************************************************************/ |
|||
|
|||
void insertglider(field_t pf){ |
|||
/*
|
|||
* # |
|||
* # |
|||
* ### |
|||
*/ |
|||
setcell(pf, 1, 0, alive); |
|||
setcell(pf, 2, 1, alive); |
|||
setcell(pf, 0, 2, alive); setcell(pf, 1, 2, alive); setcell(pf, 2, 2, alive); |
|||
} |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
int gameoflife(){ |
|||
DEBUG_BYTE(0,0); // set debug bytes to zero
|
|||
DEBUG_BYTE(1,0); |
|||
field_t pf1,pf2; |
|||
field_t ldbuf[LOOP_DETECT_BUFFER_SIZE]={{{0}}}; // loop detect buffer
|
|||
uint8_t ldbuf_idx=0; |
|||
int x,y; |
|||
uint16_t cycle; |
|||
|
|||
//start:
|
|||
/* initalise the field with random */ |
|||
for(y=0;y<YSIZE;++y){ |
|||
for(x=0;x<XSIZE; ++x){ |
|||
setcell(pf1,x,y,(random8()&1)?alive:dead); |
|||
} |
|||
} |
|||
#ifdef GLIDER_TEST |
|||
/* initialise with glider */ |
|||
for(y=0;y<YSIZE;++y){ |
|||
for(x=0;x<XSIZE; ++x){ |
|||
setcell(pf1,x,y,dead); |
|||
} |
|||
} |
|||
insertglider(pf1); |
|||
#endif |
|||
|
|||
/* the main part */ |
|||
printpf(pf1); |
|||
for(cycle=1; cycle<GOL_CYCLES; ++cycle){ |
|||
DEBUG_BYTE(0,(uint8_t)(GOL_CYCLES-cycle)&0xff); |
|||
DEBUG_BYTE(1, SREG); |
|||
wait(GOL_DELAY); |
|||
pfcopy(pf2,pf1); |
|||
nextiteration(pf1,pf2); |
|||
printpf(pf1); |
|||
/* loop detection */ |
|||
if(!pfcmp(pf1, pf2)){ |
|||
insertglider(pf1); |
|||
cycle=1; |
|||
} |
|||
if(pfempty(pf1)){ |
|||
/* kill game */ |
|||
return 0; |
|||
} |
|||
/* */ |
|||
uint8_t i; |
|||
for(i=0; i<LOOP_DETECT_BUFFER_SIZE; ++i){ |
|||
if(!pfcmp(pf1, ldbuf[i])){ |
|||
insertglider(pf1); |
|||
cycle=1; |
|||
} |
|||
} |
|||
pfcopy(ldbuf[ldbuf_idx], pf1); |
|||
ldbuf_idx = (ldbuf_idx+1)%LOOP_DETECT_BUFFER_SIZE; |
|||
|
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
@ -0,0 +1,14 @@ |
|||
/**
|
|||
* |
|||
* |
|||
* |
|||
* |
|||
* |
|||
*/ |
|||
|
|||
#ifndef GAMEOFLIFE_H_ |
|||
#define GAMEOFLIFE_H_ |
|||
|
|||
void gameoflife(); |
|||
|
|||
#endif /* GAMEOFLIFE_H_ */ |
@ -0,0 +1,98 @@ |
|||
|
|||
#include "../config.h" |
|||
#include <stdint.h> |
|||
#include "../random/prng.h" |
|||
#include "../pixel.h" |
|||
#include "../util.h" |
|||
|
|||
|
|||
typedef struct{ |
|||
pixel start; |
|||
unsigned char len; |
|||
unsigned char decay; |
|||
unsigned char index; |
|||
unsigned char speed; |
|||
} streamer; |
|||
|
|||
typedef uint8_t pixel_matrix_t[NUM_COLS][NUM_ROWS/4]; |
|||
|
|||
inline static uint8_t get_bright(pixel_matrix_t *matrix, uint8_t x, uint8_t y){ |
|||
uint8_t ret; |
|||
ret = (*matrix)[x][y/4]; |
|||
return 0x3&(ret>>(2*(y%4))); |
|||
} |
|||
|
|||
inline static void set_bright(pixel_matrix_t *matrix, uint8_t x, uint8_t y, uint8_t value){ |
|||
uint8_t t; |
|||
t = (*matrix)[x][y/4]; |
|||
t &= ~(0x3<<(2*(y%4))); |
|||
t |= value<<(2*(y%4)); |
|||
(*matrix)[x][y/4] = t; |
|||
} |
|||
|
|||
void matrix() { |
|||
unsigned int counter = 500; /* run 500 cycles */ |
|||
streamer streamers[STREAMER_NUM]; |
|||
pixel_matrix_t matrix_bright; |
|||
unsigned char x, y; |
|||
unsigned char index = 0; |
|||
unsigned char draw; |
|||
unsigned char streamer_num = 0; |
|||
|
|||
while(counter--){ |
|||
unsigned char i, j; |
|||
/* initialise matrix-buffer */ |
|||
for(x=0;x<NUM_COLS;x++) |
|||
for(y=0;y<NUM_ROWS/4;y++) |
|||
matrix_bright[x][y]=0; |
|||
|
|||
for(i=0;i<streamer_num;i++){ |
|||
streamer str = streamers[i]; |
|||
|
|||
unsigned char bright = 0xFF; draw = 0; |
|||
for(j=(str.len/8);j!=0xFF;j--){ /* Draw streamer */ |
|||
if(j+str.start.y<NUM_ROWS){ |
|||
if(bright>>6) /* bright>>6 */ |
|||
draw = 1; |
|||
if(bright > (get_bright(&matrix_bright, str.start.x, str.start.y+j)<<6) ){ |
|||
set_bright(&matrix_bright, str.start.x, str.start.y+j, bright>>6); |
|||
|
|||
} |
|||
} |
|||
bright-=((bright>>5)*str.decay); |
|||
} |
|||
|
|||
str.len+=str.speed/2; |
|||
streamers[i] = str; |
|||
if(!draw){ |
|||
for(j=i;j<streamer_num-1;j++){ |
|||
streamers[j] = streamers[j+1]; |
|||
} |
|||
streamer_num--; |
|||
i--; |
|||
} |
|||
} |
|||
|
|||
for(y=0;y<NUM_ROWS;y++) |
|||
for(x=0;x<NUM_COLS;x++){ |
|||
setpixel((pixel){x,y}, get_bright(&matrix_bright,x,y)); |
|||
} |
|||
|
|||
unsigned char nsc; |
|||
for(nsc=0;nsc<6;nsc++){ |
|||
if(streamer_num<STREAMER_NUM){ |
|||
unsigned char sy = random8()%(2*NUM_ROWS); |
|||
if (sy>NUM_ROWS-1) sy=0; |
|||
streamers[streamer_num] = (streamer){{random8()%NUM_COLS, sy}, 0, (random8()%8)+12, index++,(random8()%16)+3}; |
|||
streamer_num++; |
|||
} |
|||
} |
|||
wait(60); |
|||
|
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,14 @@ |
|||
/**
|
|||
* |
|||
* |
|||
* |
|||
* |
|||
* |
|||
*/ |
|||
|
|||
#ifndef MATRIX_H_ |
|||
#define MATRIX_H_ |
|||
|
|||
void matrix(); |
|||
|
|||
#endif /* MATRIX_H_ */ |
@ -0,0 +1,227 @@ |
|||
|
|||
#include "../config.h" |
|||
#include "../random/prng.h" |
|||
#include "../pixel.h" |
|||
#include "../util.h" |
|||
|
|||
#ifdef AVR |
|||
#include <avr/io.h> |
|||
#endif |
|||
|
|||
#define RANDOM8() (random8()) |
|||
|
|||
#ifdef ANIMATION_TESTS |
|||
void test1(){ |
|||
unsigned char x,y; |
|||
for (y=0;y<NUM_ROWS;y++){ |
|||
for (x=0;x<NUM_COLS;x++){ |
|||
setpixel((pixel){x,y}, 3); |
|||
wait(100); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void test_level1(){ |
|||
unsigned char x,y; |
|||
for (y=0;y<NUM_ROWS;y++){ |
|||
for (x=0;x<NUM_COLS;x++){ |
|||
setpixel((pixel){x,y}, 1); |
|||
wait(5); |
|||
} |
|||
} |
|||
for(;;) wait(100); |
|||
} |
|||
|
|||
void test_level2(){ |
|||
unsigned char x,y; |
|||
for (y=0;y<NUM_ROWS;y++){ |
|||
for (x=0;x<NUM_COLS;x++){ |
|||
setpixel((pixel){x,y}, 2); |
|||
wait(5); |
|||
} |
|||
} |
|||
for(;;) wait(100); |
|||
} |
|||
|
|||
void test_level3(){ |
|||
unsigned char x,y; |
|||
for (y=0;y<NUM_ROWS;y++){ |
|||
for (x=0;x<NUM_COLS;x++){ |
|||
setpixel((pixel){x,y}, 3); |
|||
wait(5); |
|||
} |
|||
} |
|||
for(;;) wait(100); |
|||
} |
|||
|
|||
void test_levels(){ |
|||
unsigned char x,y,b; |
|||
for(b=1;b<4;b++){ |
|||
for (y=0;y<NUM_ROWS;y++){ |
|||
for (x=0;x<NUM_COLS;x++){ |
|||
setpixel((pixel){x,y}, b); |
|||
wait(5); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void test_palette(){ |
|||
unsigned char x,y,b; |
|||
for (y=0;y<NUM_ROWS;y++){ |
|||
b=y%4; |
|||
for (x=0;x<NUM_COLS;x++){ |
|||
setpixel((pixel){x,y}, b); |
|||
wait(1); |
|||
} |
|||
} |
|||
for(;;) wait(100); |
|||
} |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_OFF |
|||
void off() |
|||
{ |
|||
clear_screen(0); |
|||
|
|||
while(1) |
|||
wait(100); |
|||
|
|||
} |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_SPIRALE |
|||
void spirale(unsigned int delay){ |
|||
clear_screen(0); |
|||
|
|||
cursor cur; |
|||
cur.dir = right; |
|||
cur.mode = set; |
|||
set_cursor (&cur, (pixel){NUM_COLS-1,0}); |
|||
|
|||
unsigned char clearbit=0; |
|||
while(clearbit == 0){ |
|||
|
|||
clearbit = 1; |
|||
while (!get_next_pixel(cur.pos, cur.dir)){ |
|||
clearbit = 0; |
|||
walk(&cur, 1, delay); |
|||
} |
|||
cur.dir = direction_r(cur.dir); |
|||
} |
|||
|
|||
cur.mode = clear; |
|||
set_cursor(&cur, (pixel){(NUM_COLS/2)-1,(NUM_ROWS/2)-1}); |
|||
|
|||
for(clearbit=0;clearbit==0;){ |
|||
if( get_next_pixel(cur.pos, direction_r(cur.dir)) ){ |
|||
cur.dir = direction_r(cur.dir); |
|||
} |
|||
if( get_next_pixel(cur.pos, cur.dir) == 1 ){ |
|||
walk(&cur , 1, delay); |
|||
}else{ |
|||
clearbit = 1; |
|||
} |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_JOERN1 |
|||
void joern1(){ |
|||
unsigned char i, j, x; |
|||
unsigned char rolr=0x01 , rol; |
|||
clear_screen(3); |
|||
for(i = 0; i< 80;i++){ |
|||
rol = rolr; |
|||
for(j = 0 ;j < NUM_ROWS; j++){ |
|||
for(x=0;x<LINEBYTES;x++) |
|||
pixmap[2][j][x] = rol; |
|||
if((rol<<=1)==0)rol = 0x01; |
|||
} |
|||
if((rolr<<=1) == 0) rolr = 1; |
|||
wait(100); |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_SCHACHBRETT |
|||
void schachbrett(unsigned char times){ |
|||
clear_screen(0); |
|||
unsigned char j; |
|||
for(j=0;j<times;j++){ |
|||
unsigned char i, x; |
|||
for(i = 0; i<NUM_ROWS; i++){ |
|||
for(x=0;x<LINEBYTES;x++) |
|||
pixmap[2][i][x] = 0x55<<(i&0x01); |
|||
} |
|||
wait(200); |
|||
for(i = 0; i<NUM_ROWS; i++){ |
|||
for(x=0;x<LINEBYTES;x++) |
|||
pixmap[2][i][x] = 0xAA>>(i&0x01); |
|||
} |
|||
wait(200); |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
|
|||
#ifdef ANIMATION_FEUER |
|||
#define FEUER_Y (NUM_ROWS + 3) |
|||
|
|||
void feuer() |
|||
{ |
|||
unsigned char y, x; |
|||
unsigned int t; |
|||
unsigned char world[NUM_COLS][FEUER_Y]; // double buffer
|
|||
|
|||
|
|||
for(t=0; t<800; t++) { |
|||
// diffuse
|
|||
for(y=1; y<FEUER_Y; y++) { |
|||
for(x=1; x<NUM_COLS-1; x++) { |
|||
world[x][y-1] = (FEUER_N*world[x-1][y] + FEUER_S*world[x][y] + FEUER_N*world[x+1][y]) / FEUER_DIV; |
|||
}; |
|||
|
|||
world[0][y-1] = (FEUER_N*world[NUM_COLS-1][y] + FEUER_S*world[0][y] + FEUER_N*world[1][y]) / FEUER_DIV; |
|||
world[NUM_COLS-1][y-1] = (FEUER_N*world[0][y] + FEUER_S*world[NUM_COLS-1][y] + FEUER_N*world[NUM_COLS-2][y]) / FEUER_DIV; |
|||
}; |
|||
|
|||
// update lowest line
|
|||
for(x=0; x<NUM_COLS; x++) { |
|||
world[x][FEUER_Y-1] = RANDOM8(); |
|||
}; |
|||
|
|||
// copy to screen
|
|||
for(y=0; y<NUM_ROWS; y++) { |
|||
for(x=0; x<NUM_COLS; x++) { |
|||
setpixel( (pixel){x,y}, (world[x][y] >> 5) ); |
|||
} |
|||
}; |
|||
|
|||
wait(FEUER_DELAY); |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_RANDOM_BRIGHT |
|||
/**
|
|||
* void random_bright(void) |
|||
* by Daniel Otte |
|||
* |
|||
* |
|||
*/ |
|||
void random_bright(unsigned cycles){ |
|||
uint8_t t,x,y; |
|||
while(cycles--){ |
|||
for(y=0; y<NUM_ROWS; ++y) |
|||
for(x=0; x<NUM_COLS/4; ++x){ |
|||
t=random8(); |
|||
setpixel((pixel){x*4+0, y}, 0x3&(t>>0)); |
|||
setpixel((pixel){x*4+1, y}, 0x3&(t>>2)); |
|||
setpixel((pixel){x*4+2, y}, 0x3&(t>>4)); |
|||
setpixel((pixel){x*4+3, y}, 0x3&(t>>6)); |
|||
} |
|||
wait(200); |
|||
} |
|||
} |
|||
#endif |
@ -0,0 +1,22 @@ |
|||
#ifndef PROGRAMM_H_ |
|||
#define PROGRAMM_H_ |
|||
|
|||
void off(); |
|||
void spirale(unsigned int delay); |
|||
void joern1(); |
|||
void joern2(); |
|||
void draw_line( unsigned char yabs, signed char delta); |
|||
void schachbrett(unsigned char times); |
|||
void test1(); |
|||
void test_level1(); |
|||
void test_level2(); |
|||
void test_level3(); |
|||
void test_levels(); |
|||
void test_palette(); |
|||
void snake(); |
|||
void matrix(); |
|||
void fadein(); |
|||
void feuer(); |
|||
void random_bright(unsigned cycles); |
|||
|
|||
#endif /* PROGRAMM_H_ */ |
@ -0,0 +1,249 @@ |
|||
|
|||
#include "../config.h" |
|||
#include "../pixel.h" |
|||
#include "../util.h" |
|||
#include "../random/prng.h" |
|||
#include "snake.h" |
|||
#include "../joystick.h" |
|||
|
|||
#define RANDOM8() (random8()) |
|||
|
|||
void snake(){ |
|||
pixel pixels[64]; |
|||
pixels[0] = (pixel){NUM_COLS/2, NUM_ROWS/2}; |
|||
pixels[1] = (pixel){NUM_COLS/2, (NUM_ROWS/2)-1}; |
|||
|
|||
pixel * head = &pixels[1]; |
|||
pixel * tail = &pixels[0]; |
|||
pixel old_head; |
|||
|
|||
pixel apples[10]; |
|||
unsigned char apple_num = 0; |
|||
|
|||
direction dir = up; |
|||
|
|||
clear_screen(0); |
|||
|
|||
unsigned char x=0, dead=0; |
|||
while(1){ |
|||
x++; |
|||
old_head = *head; |
|||
if(++head == pixels + 64) head = pixels; |
|||
|
|||
unsigned char dead_cnt=0; |
|||
|
|||
unsigned char apple_found = 0, j; |
|||
for(j=0;j<apple_num;j++){ |
|||
unsigned char i; |
|||
for(i=0;i<4;i++){ |
|||
if ( (next_pixel(old_head, i).x == apples[j].x) && (next_pixel(old_head, i).y == apples[j].y) ){ |
|||
apple_found = 1; |
|||
dir = i; |
|||
for(;j<apple_num-1;j++){ |
|||
apples[j]=apples[j+1]; |
|||
} |
|||
apple_num--; |
|||
goto apple_se; |
|||
} |
|||
} |
|||
} |
|||
apple_se: |
|||
|
|||
if(apple_found){ |
|||
|
|||
}else{ |
|||
while(get_next_pixel(old_head, dir)){ |
|||
if((dead_cnt++)==4){ |
|||
dead = 1; |
|||
break; |
|||
} |
|||
dir = direction_r(dir); |
|||
} |
|||
} |
|||
|
|||
if(!dead){ |
|||
*head = next_pixel(old_head, dir); |
|||
setpixel(*head, 3); |
|||
|
|||
if((RANDOM8()&0xff)<80){ |
|||
unsigned char j; |
|||
unsigned char nextapple=0, distx, disty, shortdist=255, xy=0; |
|||
if(!apple_num){ |
|||
dir = RANDOM8()%4; |
|||
}else{ |
|||
for(j=0;j<apple_num;j++){ |
|||
if(head->x > apples[j].x){ |
|||
distx = head->x - apples[j].x; |
|||
}else{ |
|||
distx = apples[j].x - head->x; |
|||
} |
|||
if(head->y > apples[j].y){ |
|||
disty = head->y - apples[j].y; |
|||
}else{ |
|||
disty = apples[j].y - head->y; |
|||
} |
|||
if ((distx + disty) < shortdist){ |
|||
shortdist = distx + disty; |
|||
nextapple = j; |
|||
xy = (distx > disty)?1:0; |
|||
} |
|||
} |
|||
if(xy){ |
|||
dir = (apples[nextapple].x > head->x)?left:right; |
|||
}else{ |
|||
dir = (apples[nextapple].y > head->y)?down:up; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if( (apple_num<9) && ((RANDOM8()&0xff)<10) ){ |
|||
pixel new_apple = (pixel){RANDOM8()%NUM_COLS,RANDOM8()%NUM_ROWS}; |
|||
if(!get_pixel(new_apple)){ |
|||
apples[apple_num++]=new_apple; |
|||
} |
|||
} |
|||
|
|||
if(!apple_found){ |
|||
clearpixel(*tail); |
|||
if(++tail == pixels + 64) tail = pixels; |
|||
} |
|||
}else{ |
|||
while(tail != head){ |
|||
clearpixel(*tail); |
|||
if((++tail)>pixels+64) tail = pixels; |
|||
wait (60); |
|||
} |
|||
break; |
|||
} |
|||
|
|||
for(j=0;j<apple_num;j++){ |
|||
if(x%2){ |
|||
setpixel(apples[j], 3); |
|||
}else{ |
|||
clearpixel(apples[j]); |
|||
} |
|||
} |
|||
|
|||
wait (SNAKE_DELAY); |
|||
} |
|||
} |
|||
|
|||
void snake_game() { |
|||
pixel pixels[64] = {{4, 14},{4, 13}}; |
|||
pixel * head = &pixels[1]; |
|||
pixel * tail = &pixels[0]; |
|||
pixel old_head; |
|||
pixel apples[10]; |
|||
uint8_t joy, joy_old=0xff, joy_cmd=0xff; |
|||
|
|||
unsigned char x, y, dead = 0; |
|||
unsigned char apple_num = 0; |
|||
direction dir = up; |
|||
|
|||
unsigned char apple_found = 0; |
|||
unsigned char j; |
|||
|
|||
clear_screen(0); |
|||
|
|||
// zeichne Rahmen
|
|||
for (x = 0; x < NUM_COLS; x++) { |
|||
for (y = 0; y < NUM_ROWS; y++) { |
|||
if (((x == 0) || (x == NUM_COLS-1)) || |
|||
((y == 0) || (y == NUM_ROWS-1))) { |
|||
setpixel((pixel) {x, y}, 3); |
|||
} |
|||
} |
|||
} |
|||
|
|||
x = 0; |
|||
while (1) { |
|||
|
|||
x++; |
|||
old_head = *head; |
|||
++head; |
|||
if (head == pixels + 64) |
|||
head = pixels; |
|||
|
|||
if (joy_cmd == right) { |
|||
dir = direction_r(dir); |
|||
joy_cmd = 0xff; |
|||
} else if (joy_cmd == left) { |
|||
dir = direction_r(dir); |
|||
dir = direction_r(dir); |
|||
dir = direction_r(dir); |
|||
joy_cmd = 0xff; |
|||
} |
|||
|
|||
// kopf einen weiter bewegen
|
|||
*head = next_pixel(old_head, dir); |
|||
|
|||
apple_found = 0; |
|||
|
|||
// prfen ob man auf nen Apfel drauf ist
|
|||
for (j = 0; j < apple_num; j++) { |
|||
if ( ( head->x == apples[j].x) && |
|||
(head->y == apples[j].y) ){ |
|||
apple_found = 1; |
|||
for(; j < apple_num - 1; j++) { |
|||
apples[j] = apples[j+1]; |
|||
} |
|||
apple_num--; |
|||
goto apple_se; |
|||
} |
|||
} |
|||
if (get_pixel(*head)) { |
|||
dead = 1; |
|||
} |
|||
apple_se: |
|||
|
|||
if (!dead) { |
|||
setpixel(*head, 3); |
|||
|
|||
// setze neue pfel
|
|||
if ( (apple_num < 9) && (random8() < 10) ) { |
|||
pixel new_apple = (pixel) {(random8() % (NUM_COLS-2))+1, |
|||
(random8() % (NUM_ROWS-2))+1}; |
|||
if (!get_pixel(new_apple)){ |
|||
apples[apple_num++] = new_apple; |
|||
} |
|||
} |
|||
// lsche Ende
|
|||
if (!apple_found && !dead) { |
|||
clearpixel(*tail); |
|||
if (++tail == pixels + 64) |
|||
tail = pixels; |
|||
} |
|||
} else { |
|||
while (tail != head) { |
|||
clearpixel(*tail); |
|||
if ((++tail) > pixels + 64) |
|||
tail = pixels; |
|||
wait (60); |
|||
} |
|||
break; |
|||
} |
|||
|
|||
for (j = 0; j < apple_num; j++) { |
|||
if (x % 2) { |
|||
setpixel(apples[j], 3); |
|||
} else { |
|||
clearpixel(apples[j]); |
|||
} |
|||
} |
|||
for(j=0;j<20;j++){ |
|||
if(JOYISLEFT){ |
|||
joy = left; |
|||
}else if(JOYISRIGHT){ |
|||
joy = right; |
|||
}else{ |
|||
joy = 0xff; |
|||
} |
|||
if(joy != joy_old){ |
|||
joy_cmd = joy; |
|||
} |
|||
joy_old = joy; |
|||
wait (5); |
|||
} |
|||
} |
|||
} |
|||
|
@ -0,0 +1,8 @@ |
|||
#ifndef SNAKE_H_ |
|||
#define SNAKE_H_ |
|||
|
|||
void snake(); |
|||
void snake_game(); |
|||
|
|||
|
|||
#endif /* SNAKE_H_ */ |
@ -0,0 +1,31 @@ |
|||
TARGET = libborg_hw.a |
|||
TOPDIR = .. |
|||
|
|||
include $(TOPDIR)/defaults.mk |
|||
|
|||
|
|||
ifeq ($(BORG_HW),HW_BORG_16) |
|||
SRC = borg_hw_borg16.c |
|||
endif |
|||
|
|||
ifeq ($(BORG_HW),HW_BORG_ANDRE) |
|||
SRC = borg_hw_andreborg.c |
|||
endif |
|||
|
|||
ifeq ($(BORG_HW),HW_BORG_LS) |
|||
SRC = borg_hw_borg_ls.c |
|||
endif |
|||
|
|||
ifeq ($(BORG_HW),HW_BORG_LS) |
|||
SRC = borg_hw_borg_ls.c |
|||
endif |
|||
|
|||
ifeq ($(BORG_HW),HW_BORG_MINI) |
|||
SRC = borg_hw_borg_mini.c |
|||
endif |
|||
|
|||
ifeq ($(SRC),'') |
|||
$(error no valid hardware driver selected ) |
|||
endif |
|||
|
|||
include $(TOPDIR)/rules.mk |
@ -0,0 +1,15 @@ |
|||
#ifndef BORG_HW_H |
|||
#define BORG_HW_H |
|||
|
|||
//Linebytes gibt die Zahl der Bytes pro Zeile in der
|
|||
//Pixmap an, also Spaltenzahl/8 aufgerundet
|
|||
#define LINEBYTES (((NUM_COLS-1)/8)+1) |
|||
|
|||
|
|||
extern unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; |
|||
|
|||
void watchdog_enable(); |
|||
void borg_hw_init(); |
|||
void timer0_off(); |
|||
|
|||
#endif |
@ -0,0 +1,168 @@ |
|||
|
|||
#include "../config.h" |
|||
#include "../makros.h" |
|||
|
|||
#include <avr/interrupt.h> |
|||
#include <avr/io.h> |
|||
#include <avr/wdt.h> |
|||
#include "borg_hw.h" |
|||
|
|||
/*
|
|||
// Diese #defines werden nun durch menuconfig gesetzt
|
|||
|
|||
// 16 Spalten insgesamt direkt gesteuert, dafür 2 Ports
|
|||
#define COLPORT1 PORTA |
|||
#define COLDDR1 DDRA |
|||
|
|||
#define COLPORT2 PORTC |
|||
#define COLDDR2 DDRC |
|||
|
|||
// Der andere Port übernimmt die Steuerung der Schieberegister
|
|||
#define ROWPORT PORTD |
|||
#define ROWDDR DDRD |
|||
// Clock und reset gehen gemeinsam an beide Schieberegister
|
|||
// der reset pin ist negiert
|
|||
#define PIN_MCLR PD4 |
|||
#define PIN_CLK PD5 |
|||
//das dier sind die individuellen Dateneingänge für die Schieberegister
|
|||
#define PIN_DATA1 PD6 |
|||
#define PIN_DATA2 PD7 |
|||
*/ |
|||
|
|||
#define COLDDR1 DDR(COLPORT1) |
|||
#define COLDDR2 DDR(COLPORT2) |
|||
#define ROWDDR DDR(ROWPORT) |
|||
|
|||
//Der Puffer, in dem das aktuelle Bild gespeichert wird
|
|||
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; |
|||
|
|||
|
|||
//Eine Zeile anzeigen
|
|||
inline void rowshow(unsigned char row, unsigned char plane){ |
|||
//Die Zustände von der vorherigen Zeile löschen
|
|||
COLPORT1 = 0; |
|||
COLPORT2 = 0; |
|||
|
|||
//kurze Warteschleife, damit die Treiber auch wirklich ausschalten
|
|||
unsigned char i; |
|||
for(i=0;i<20;i++){ |
|||
asm volatile("nop"); |
|||
} |
|||
|
|||
|
|||
if (row == 0){ |
|||
//Zeile 0: Das erste Schieberegister initialisieren
|
|||
ROWPORT&= ~(1<<PIN_MCLR); |
|||
ROWPORT|= (1<<PIN_MCLR); |
|||
ROWPORT|= (1<<PIN_DATA1); |
|||
ROWPORT|= (1<<PIN_CLK); |
|||
ROWPORT&= ~(1<<PIN_CLK); |
|||
ROWPORT&= ~(1<<PIN_DATA1); |
|||
|
|||
//Je nachdem, welche der Ebenen wir Zeichnen, die Zeile verschieden lange Anzeigen
|
|||
switch (plane){ |
|||
case 0: |
|||
OCR0 = 5; |
|||
break; |
|||
case 1: |
|||
OCR0 = 8; |
|||
break; |
|||
case 2: |
|||
OCR0 = 20; |
|||
} |
|||
}else if(row == 8){ |
|||
//Zeile 8: Das Zweite Schieberegister initialisieren
|
|||
ROWPORT&= ~(1<<PIN_MCLR); |
|||
ROWPORT|= (1<<PIN_MCLR); |
|||
ROWPORT|= (1<<PIN_DATA2); |
|||
ROWPORT|= (1<<PIN_CLK); |
|||
ROWPORT&= ~(1<<PIN_CLK); |
|||
ROWPORT&= ~(1<<PIN_DATA2); |
|||
}else{ |
|||
//In jeder anderen Zeile einfach nur einen weiter schieben
|
|||
ROWPORT|= (1<<PIN_CLK); |
|||
ROWPORT&= ~(1<<PIN_CLK); |
|||
} |
|||
|
|||
//ncoh eine Warteschleife, damit die Zeilentreiber bereit sind
|
|||
for(i=0;i<20;i++){ |
|||
asm volatile("nop"); |
|||
} |
|||
|
|||
//die Daten für die aktuelle Zeile auf die Spaltentreiber ausgeben
|
|||
COLPORT1 = pixmap[plane][row][0]; |
|||
COLPORT2 = pixmap[plane][row][1]; |
|||
} |
|||
|
|||
|
|||
//Dieser Interrupt wird je nach Ebene mit 50kHz 31,25kHz oder 12,5kHz ausgeführt
|
|||
SIGNAL(SIG_OUTPUT_COMPARE0) |
|||
{ |
|||
static unsigned char plane = 0; |
|||
static unsigned char row = 0; |
|||
|
|||
//Watchdog zurücksetzen
|
|||
wdt_reset(); |
|||
|
|||
//Die aktuelle Zeile in der aktuellen Ebene ausgeben
|
|||
rowshow(row, plane); |
|||
|
|||
//Zeile und Ebene inkrementieren
|
|||
if(++row == NUM_ROWS){ |
|||
row = 0; |
|||
if(++plane==NUMPLANE) plane=0; |
|||
} |
|||
} |
|||
|
|||
|
|||
void timer0_off(){ |
|||
cli(); |
|||
|
|||
COLPORT1 = 0; |
|||
COLPORT2 = 0; |
|||
ROWPORT = 0; |
|||
|
|||
TCCR0 = 0x00; |
|||
sei(); |
|||
} |
|||
|
|||
|
|||
// Den Timer, der denn Interrupt auslöst, initialisieren
|
|||
void timer0_on(){ |
|||
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
|
|||
CS02 CS01 CS00 |
|||
0 0 0 stop |
|||
0 0 1 clk |
|||
0 1 0 clk/8 |
|||
0 1 1 clk/64 |
|||
1 0 0 clk/256 |
|||
1 0 1 clk/1024 |
|||
|
|||
*/ |
|||
TCCR0 = 0x0B; // CTC Mode, clk/64
|
|||
TCNT0 = 0; // reset timer
|
|||
OCR0 = 20; // Compare with this value
|
|||
TIMSK = 0x02; // Compare match Interrupt on
|
|||
} |
|||
|
|||
void borg_hw_init(){ |
|||
//Spalten Ports auf Ausgang
|
|||
COLDDR1 = 0xFF; |
|||
COLDDR2 = 0xFF; |
|||
|
|||
//Pins am Zeilenport auf Ausgang
|
|||
ROWDDR = (1<<PIN_MCLR) | (1<<PIN_CLK) | (1<< PIN_DATA1) | (1<<PIN_DATA2); |
|||
|
|||
//Alle Spalten erstmal aus
|
|||
COLPORT1 = 0; |
|||
COLPORT2 = 0; |
|||
|
|||
//Schieberegister für Zeilen zurücksetzen
|
|||
ROWPORT = 0; |
|||
|
|||
timer0_on(); |
|||
|
|||
//Watchdog Timer aktivieren
|
|||
wdt_reset(); |
|||
wdt_enable(0x00); // 17ms Watchdog
|
|||
} |
@ -0,0 +1,207 @@ |
|||
|
|||
#include "../config.h" |
|||
#include "../makros.h" |
|||
|
|||
#include <avr/interrupt.h> |
|||
#include <avr/io.h> |
|||
#include <avr/wdt.h> |
|||
#include "borg_hw.h" |
|||
|
|||
/*
|
|||
// Diese #defines werden nun durch menuconfig gesetzt
|
|||
|
|||
// 16 Spalten insgesamt direkt gesteuert, dafür 2 Ports
|
|||
#define COLPORT1 PORTC |
|||
#define COLDDR1 DDRC |
|||
|
|||
#define COLPORT2 PORTA |
|||
#define COLDDR2 DDRA |
|||
|
|||
// Der andere Port übernimmt die Steuerung der Schieberegister
|
|||
#define ROWPORT PORTD |
|||
#define ROWDDR DDRD |
|||
// Clock und reset gehen gemeinsam an beide Schieberegister
|
|||
// der reset pin ist negiert
|
|||
#define PIN_MCLR PD4 |
|||
#define PIN_CLK PD6 |
|||
//das dier sind die individuellen Dateneingänge für die Schieberegister
|
|||
#define PIN_DATA PD7 |
|||
*/ |
|||
|
|||
#define COLDDR1 DDR(COLPORT1) |
|||
#define COLDDR2 DDR(COLPORT2) |
|||
#define ROWDDR DDR(ROWPORT) |
|||
|
|||
//Der Puffer, in dem das aktuelle Bild gespeichert wird
|
|||
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; |
|||
|
|||
|
|||
//zur nächsten Zeile weiterschalten
|
|||
inline void nextrow(uint8_t row){ |
|||
//Die Zustände von der vorherigen Zeile löschen
|
|||
COLPORT1 = 0; |
|||
COLPORT2 = 0; |
|||
|
|||
//kurze Warteschleife, damit die Treiber auch wirklich ausschalten
|
|||
|
|||
unsigned char i; |
|||
for(i=0;i<10;i++){ |
|||
asm volatile("nop"); |
|||
} |
|||
|
|||
if (row == 0){ |
|||
//Zeile 0: Das erste Schieberegister initialisieren
|
|||
#ifndef INVERSE_ROWS |
|||
ROWPORT&= ~(1<<PIN_MCLR); |
|||
ROWPORT|= (1<<PIN_MCLR); |
|||
ROWPORT|= (1<<PIN_DATA); |
|||
ROWPORT|= (1<<PIN_CLK); |
|||
ROWPORT&= ~(1<<PIN_CLK); |
|||
ROWPORT&= ~(1<<PIN_DATA); |
|||
#else |
|||
ROWPORT&= ~(1<<PIN_DATA); |
|||
ROWPORT|= (1<<PIN_CLK); |
|||
ROWPORT&= ~(1<<PIN_CLK); |
|||
ROWPORT|= (1<<PIN_DATA); |
|||
|
|||
#endif |
|||
}else{ |
|||
//In jeder anderen Zeile einfach nur einen weiter schieben
|
|||
ROWPORT|= (1<<PIN_CLK); |
|||
ROWPORT&= ~(1<<PIN_CLK); |
|||
} |
|||
|
|||
//noch eine Warteschleife, damit die Zeilentreiber bereit sind
|
|||
for(i=0;i<20;i++){ |
|||
asm volatile("nop"); |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
//Eine Zeile anzeigen
|
|||
inline void rowshow(unsigned char row, unsigned char plane){ |
|||
//Je nachdem, welche der Ebenen wir Zeichnen, die Zeile verschieden lange Anzeigen
|
|||
switch (plane){ |
|||
case 0: |
|||
OCR0 = 3; |
|||
break; |
|||
case 1: |
|||
OCR0 = 4; |
|||
break; |
|||
case 2: |
|||
OCR0 = 22; |
|||
} |
|||
|
|||
uint8_t tmp, tmp1; |
|||
//die Daten für die aktuelle Zeile auf die Spaltentreiber ausgeben
|
|||
|
|||
#ifndef INTERLACED_ROWS |
|||
tmp = pixmap[plane][row][0]; |
|||
tmp1 = pixmap[plane][row][1]; |
|||
#else |
|||
row = (row>>1) + ((row & 0x01)?8:0 ); |
|||
tmp = pixmap[plane][row][0]; |
|||
tmp1 = pixmap[plane][row][1]; |
|||
#endif |
|||
#ifdef REVERSED_HARDWARE |
|||
tmp = (tmp >> 4) | (tmp << 4); |
|||
tmp = ((tmp & 0xcc) >> 2) | ((tmp & 0x33)<< 2); //0xcc = 11001100, 0x33 = 00110011
|
|||
tmp = ((tmp & 0xaa) >> 1) | ((tmp & 0x55)<< 1); //0xaa = 10101010, 0x55 = 1010101
|
|||
COLPORT2 = tmp; |
|||
tmp = tmp1; |
|||
tmp = (tmp >> 4) | (tmp << 4); |
|||
tmp = ((tmp & 0xcc) >> 2) | ((tmp & 0x33) << 2); //0xcc = 11001100, 0x33 = 00110011
|
|||
tmp = ((tmp & 0xaa) >> 1) | ((tmp & 0x55) << 1); //0xaa = 10101010, 0x55 = 1010101
|
|||
COLPORT1 = tmp; |
|||
#else |
|||
#ifdef INTERLACED_COLS |
|||
static uint8_t interlace_table[16] = { |
|||
0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 |
|||
}; |
|||
COLPORT1 = interlace_table[tmp&0x0f] | (interlace_table[tmp1&0x0f]<<1); |
|||
tmp>>=4; tmp1>>=4; |
|||
COLPORT2 = interlace_table[tmp] | (interlace_table[tmp1]<<1); |
|||
#else |
|||
COLPORT1 = tmp; |
|||
COLPORT2 = tmp1; |
|||
#endif |
|||
#endif |
|||
|
|||
} |
|||
|
|||
|
|||
//Dieser Interrupt wird je nach Ebene mit 50kHz 31,25kHz oder 12,5kHz ausgeführt
|
|||
SIGNAL(SIG_OUTPUT_COMPARE0) |
|||
{ |
|||
static unsigned char plane = 0; |
|||
static unsigned char row = 0; |
|||
|
|||
//Watchdog zurücksetzen
|
|||
wdt_reset(); |
|||
|
|||
//Zeile und Ebene inkrementieren
|
|||
if(++plane==NUMPLANE){ |
|||
plane=0; |
|||
if(++row == NUM_ROWS){ |
|||
row = 0; |
|||
} |
|||
nextrow(row); |
|||
} |
|||
|
|||
//Die aktuelle Zeile in der aktuellen Ebene ausgeben
|
|||
rowshow(row, plane); |
|||
} |
|||
|
|||
|
|||
void timer0_off(){ |
|||
cli(); |
|||
|
|||
COLPORT1 = 0; |
|||
COLPORT2 = 0; |
|||
ROWPORT = 0; |
|||
|
|||
TCCR0 = 0x00; |
|||
sei(); |
|||
} |
|||
|
|||
|
|||
// Den Timer, der denn Interrupt auslöst, initialisieren
|
|||
void timer0_on(){ |
|||
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
|
|||
CS02 CS01 CS00 |
|||
0 0 0 stop |
|||
0 0 1 clk |
|||
0 1 0 clk/8 |
|||
0 1 1 clk/64 |
|||
1 0 0 clk/256 |
|||
1 0 1 clk/1024 |
|||
|
|||
*/ |
|||
TCCR0 = 0x0C; // CTC Mode, clk/64
|
|||
TCNT0 = 0; // reset timer
|
|||
OCR0 = 20; // Compare with this value
|
|||
TIMSK = 0x02; // Compare match Interrupt on
|
|||
} |
|||
|
|||
void borg_hw_init(){ |
|||
//Spalten Ports auf Ausgang
|
|||
COLDDR1 = 0xFF; |
|||
COLDDR2 = 0xFF; |
|||
|
|||
//Pins am Zeilenport auf Ausgang
|
|||
ROWDDR = (1<<PIN_MCLR) | (1<<PIN_CLK) | (1<< PIN_DATA); |
|||
|
|||
//Alle Spalten erstmal aus
|
|||
COLPORT1 = 0; |
|||
COLPORT2 = 0; |
|||
|
|||
//Schieberegister für Zeilen zurücksetzen
|
|||
ROWPORT = 0; |
|||
|
|||
timer0_on(); |
|||
|
|||
//Watchdog Timer aktivieren
|
|||
wdt_reset(); |
|||
wdt_enable(0x00); // 17ms Watchdog
|
|||
} |
@ -0,0 +1,127 @@ |
|||
|
|||
#include "../config.h" |
|||
#include "../makros.h" |
|||
|
|||
#include <avr/interrupt.h> |
|||
#include <avr/io.h> |
|||
#include <avr/wdt.h> |
|||
|
|||
#include "borg_hw.h" |
|||
|
|||
/*
|
|||
// Diese #defines werden nun durch menuconfig gesetzt
|
|||
|
|||
#define ROWPORT PORTB |
|||
#define ROWDDR DDRB |
|||
|
|||
#define COLPORT PORTD |
|||
#define COLDDR DDRD |
|||
|
|||
#define PIN_DATA PC4 |
|||
#define PIN_CLK PC6 //active low
|
|||
#define PIN_LINE_EN PC5 //active low
|
|||
|
|||
*/ |
|||
|
|||
#define COLDDR DDR(COLPORT) |
|||
#define ROWDDR DDR(ROWPORT) |
|||
|
|||
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; |
|||
|
|||
|
|||
inline void rowshow(unsigned char row, unsigned char plane){ |
|||
COLPORT |= (1<<PIN_LINE_EN);//blank display
|
|||
|
|||
ROWPORT = (ROWPORT & 0xF8) | row; |
|||
|
|||
|
|||
unsigned char b, d, x; |
|||
for(b=0;b<LINEBYTES;b++){ |
|||
d = pixmap[plane][row][b]; |
|||
for(x=0;x<8;x++){ |
|||
if(d & 0x01){ |
|||
COLPORT |= (1<<PIN_DATA); |
|||
}else{ |
|||
COLPORT &= ~(1<<PIN_DATA); |
|||
} |
|||
d>>=1; |
|||
COLPORT &= ~(1<<PIN_CLK); |
|||
COLPORT |= (1<<PIN_CLK); |
|||
} |
|||
} |
|||
|
|||
COLPORT &= ~(1<<PIN_LINE_EN);//unblank display
|
|||
} |
|||
|
|||
SIGNAL(SIG_OUTPUT_COMPARE0) |
|||
{ |
|||
static unsigned char plane = 0; |
|||
static unsigned char row = 0; |
|||
|
|||
if (row == 0){ |
|||
switch (plane){ |
|||
case 0: |
|||
OCR0 = 7; |
|||
break; |
|||
case 1: |
|||
OCR0 = 20; |
|||
break; |
|||
case 2: |
|||
OCR0 = 40; |
|||
} |
|||
} |
|||
|
|||
rowshow(row, plane); |
|||
|
|||
if(++row == NUM_ROWS){ |
|||
row = 0; |
|||
if(++plane==NUMPLANE) plane=0; |
|||
} |
|||
wdt_reset(); |
|||
} |
|||
|
|||
|
|||
|
|||
void timer0_on(){ |
|||
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
|
|||
CS02 CS01 CS00 |
|||
0 0 0 stop |
|||
0 0 1 clk |
|||
0 1 0 clk/8 |
|||
0 1 1 clk/64 |
|||
1 0 0 clk/256 |
|||
1 0 1 clk/1024 |
|||
|
|||
*/ |
|||
TCCR0 = 0x08 |0x04; // CTC Mode, clk/256
|
|||
TCNT0 = 0; // reset timer
|
|||
OCR0 = 0x30; // Compare with this value
|
|||
TIMSK = 0x02; // Compare match Interrupt on
|
|||
} |
|||
|
|||
void timer0_off(){ |
|||
cli(); |
|||
|
|||
COLPORT |= (1<<PIN_LINE_EN);//blank display
|
|||
|
|||
TCCR0 = 0x00; |
|||
sei(); |
|||
} |
|||
|
|||
void watchdog_enable() |
|||
{ |
|||
wdt_reset(); |
|||
wdt_enable(0x00); // 17ms
|
|||
|
|||
} |
|||
|
|||
void borg_hw_init(){ |
|||
COLPORT |= (1<<PIN_CLK) | (1<<PIN_LINE_EN); |
|||
COLDDR |= (1<<PIN_CLK) | (1<<PIN_LINE_EN) | (1<<PIN_DATA); |
|||
|
|||
ROWDDR |= 0x07; |
|||
|
|||
watchdog_enable(); |
|||
timer0_on(); |
|||
} |
|||
|
@ -0,0 +1,165 @@ |
|||
|
|||
#include "../config.h" |
|||
|
|||
#include <avr/signal.h> |
|||
#include <avr/interrupt.h> |
|||
#include <avr/io.h> |
|||
|
|||
#include "borg_hw.h" |
|||
|
|||
/*
|
|||
// Diese #defines werden nun durch menuconfig gesetzt
|
|||
|
|||
//An diesen Pins ist das Schieberegister
|
|||
//für die Spalten angeschlossen.
|
|||
#define COLPORT PORTC |
|||
#define COLDDR DDRC |
|||
#define BIT_DAT 4 //Daten-Eingang
|
|||
#define BIT_CLK 5 //Takt-Eingang
|
|||
|
|||
//An diesem Port sind die Zeilentreiber angeschlossen.
|
|||
//Ein Null-Pegel schaltet den jeweiligen Transistor an.
|
|||
#define ROWPORT1 PORTD |
|||
#define ROWDDR1 DDRD |
|||
|
|||
#define ROWPORT2 PORTC |
|||
#define ROWDDR2 DDRC |
|||
*/ |
|||
|
|||
#define COLDDR DDR(COLPORT) |
|||
#define ROWDDR1 DDR(ROWPORT1) |
|||
#define ROWDDR2 DDR(ROWPORT2) |
|||
|
|||
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; |
|||
|
|||
inline void rowshow(unsigned char row, unsigned char plane){ |
|||
static uint8_t rowmask = 0xFF; |
|||
uint8_t x, tmp; |
|||
|
|||
//alle Zeilentreiber aus
|
|||
ROWPORT1 |= 0xF3; |
|||
ROWPORT2 |= 0x0C; |
|||
|
|||
for(x=0;x<10;x++){ |
|||
asm volatile ("nop"); |
|||
} |
|||
|
|||
if (row == 0){ |
|||
rowmask = 0x7F; //0111 1111
|
|||
}else{ |
|||
rowmask >>= 1; |
|||
rowmask |= 0x80; |
|||
} |
|||
|
|||
switch (plane){ |
|||
case 0: |
|||
TCNT0 = 0x100-12; |
|||
break; |
|||
case 1: |
|||
TCNT0 = 0x100-20; |
|||
break; |
|||
case 2: |
|||
TCNT0 = 0x100-50; |
|||
} |
|||
|
|||
|
|||
|
|||
//Die fünf bits für das 2. Display in das
|
|||
//Schieberegister takten
|
|||
tmp = pixmap[plane][row][0]; |
|||
for(x=0;x<3;x++){ |
|||
if(tmp & 0x20){ |
|||
COLPORT &= ~(1<<BIT_DAT); |
|||
}else{ |
|||
COLPORT |= (1<<BIT_DAT); |
|||
} |
|||
tmp>>=1; |
|||
|
|||
COLPORT |= (1<<BIT_CLK); |
|||
COLPORT &= ~(1<<BIT_CLK); |
|||
} |
|||
|
|||
tmp = pixmap[plane][row][1]; |
|||
for(x=0;x<2;x++){ |
|||
if(tmp & 0x01){ |
|||
COLPORT &= ~(1<<BIT_DAT); |
|||
}else{ |
|||
COLPORT |= (1<<BIT_DAT); |
|||
} |
|||
tmp>>=1; |
|||
|
|||
COLPORT |= (1<<BIT_CLK); |
|||
COLPORT &= ~(1<<BIT_CLK); |
|||
} |
|||
|
|||
|
|||
//Die restlichen 5 bit auch ins Schieberegister
|
|||
tmp = pixmap[plane][row][0]; |
|||
for(x=0;x<5;x++){ |
|||
if(tmp & 0x01){ |
|||
COLPORT &= ~(1<<BIT_DAT); |
|||
}else{ |
|||
COLPORT |= (1<<BIT_DAT); |
|||
} |
|||
tmp>>=1; |
|||
|
|||
COLPORT |= (1<<BIT_CLK); |
|||
COLPORT &= ~(1<<BIT_CLK); |
|||
} |
|||
//nächste Zeile anschalten
|
|||
ROWPORT1 &= rowmask | 0x0C; |
|||
ROWPORT2 &= rowmask | 0xF3; |
|||
} |
|||
|
|||
extern uint8_t schmuh; |
|||
|
|||
ISR(SIG_OVERFLOW0) |
|||
{ |
|||
static unsigned char plane = 0; |
|||
static unsigned char row = 0; |
|||
|
|||
rowshow(row, plane); |
|||
|
|||
if(++row == NUM_ROWS){ |
|||
row = 0; |
|||
if(++plane==NUMPLANE) plane=0; |
|||
} |
|||
|
|||
schmuh = 1; |
|||
} |
|||
|
|||
|
|||
|
|||
void timer0_on(){ |
|||
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
|
|||
CS02 CS01 CS00 |
|||
0 0 0 stop |
|||
0 0 1 clk |
|||
0 1 0 clk/8 |
|||
0 1 1 clk/64 |
|||
1 0 0 clk/256 |
|||
1 0 1 clk/1024 |
|||
|
|||
*/ |
|||
TCCR0 = 0x03; // clk/64
|
|||
TCNT0 = 0xFF-20;// reset timer
|
|||
TIMSK |= (1<<TOIE0); |
|||
} |
|||
|
|||
|
|||
void borg_hw_init(){ |
|||
// Alle Zeilentransistoren aus.
|
|||
ROWPORT1 |= 0xF3; |
|||
// Port für Zeilentransistoren auf Ausgang
|
|||
ROWDDR1 |= 0xF3; |
|||
|
|||
ROWPORT2 |=0x0C; |
|||
ROWDDR2 |=0x0C; |
|||
|
|||
|
|||
//Signale für Schieberegister auf Ausgang
|
|||
COLDDR |= (1<<BIT_CLK) | (1<<BIT_DAT); |
|||
COLPORT &= ~(1<<BIT_CLK); |
|||
|
|||
timer0_on(); |
|||
} |
@ -0,0 +1,50 @@ |
|||
###################### Borg Hardware Menu ##################################### |
|||
mainmenu_option next_comment |
|||
comment "Borg Hardware" |
|||
|
|||
int "Number of rows " NUM_ROWS 16 |
|||
int "Number of columns" NUM_COLS 16 |
|||
int "Number of brightnes-levels" NUMPLANE 3 |
|||
|
|||
|
|||
|
|||
choice 'Hardware Driver' \ |
|||
"Borg-16 HW_BORG_16 \ |
|||
Andre-borg HW_BORG_ANDRE \ |
|||
Laufschrift-borg HW_BORG_LS \ |
|||
Borg-mini HW_BORG_MINI" \ |
|||
'Borg-16' BORG_HW |
|||
|
|||
|
|||
if [ "$BORG_HW" == "HW_BORG_16" ] ; then |
|||
source borg_hw/config_borg16.in |
|||
fi |
|||
|
|||
if [ "$BORG_HW" == "HW_BORG_ANDRE" ] ; then |
|||
source borg_hw/config_andreborg.in |
|||
fi |
|||
|
|||
if [ "$BORG_HW" == "HW_BORG_LS" ] ; then |
|||
source borg_hw/config_borg_ls.in |
|||
fi |
|||
|
|||
if [ "$BORG_HW" == "HW_BORG_MINI" ] ; then |
|||
source borg_hw/config_borg_mini.in |
|||
fi |
|||
|
|||
|
|||
|
|||
|
|||
# case $x in |
|||
# y) flag="*" ;; |
|||
# m) flag="M" ;; |
|||
# *) flag=" " ;; |
|||
# esac |
|||
|
|||
|
|||
|
|||
|
|||
endmenu |
|||
|
|||
|
|||
############################################################################### |
@ -0,0 +1,71 @@ |
|||
mainmenu_option next_comment |
|||
comment "Andreborg port setup" |
|||
|
|||
choice 'Column Port 1 (right)' \ |
|||
"PORTA PORTA \ |
|||
PORTB PORTB \ |
|||
PORTC PORTC \ |
|||
PORTD PORTD" \ |
|||
'PORTA' COLPORT1 |
|||
|
|||
choice 'Column Port 2 (left)' \ |
|||
"PORTA PORTA \ |
|||
PORTB PORTB \ |
|||
PORTC PORTC \ |
|||
PORTD PORTD" \ |
|||
'PORTC' COLPORT2 |
|||
|
|||
choice 'port for row shiftregisters' \ |
|||
"PORTA PORTA \ |
|||
PORTB PORTB \ |
|||
PORTC PORTC \ |
|||
PORTD PORTD" \ |
|||
'PORTD' ROWPORT |
|||
|
|||
comment "pin numbers on shiftregister port" |
|||
|
|||
choice '/MCLR Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin4' PIN_MCLR |
|||
|
|||
choice 'CLK Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin5' PIN_CLK |
|||
|
|||
choice 'DATA1 Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin6' PIN_DATA1 |
|||
|
|||
choice 'DATA2 Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin7' PIN_DATA2 |
|||
|
|||
endmenu |
@ -0,0 +1,77 @@ |
|||
mainmenu_option next_comment |
|||
comment "Borg16 port setup" |
|||
|
|||
#define COLPORT1 PORTC |
|||
#define COLDDR1 DDRC |
|||
|
|||
#define COLPORT2 PORTA |
|||
#define COLDDR2 DDRA |
|||
|
|||
#// Der andere Port übernimmt die Steuerung der Schieberegister |
|||
#define ROWPORT PORTD |
|||
#define ROWDDR DDRD |
|||
#// Clock und reset gehen gemeinsam an beide Schieberegister |
|||
#// der reset pin ist negiert |
|||
#define PIN_RST PD4 |
|||
#define PIN_CLK PD6 |
|||
#//das dier sind die individuellen Dateneingänge für die Schieberegister |
|||
#define PIN_SHFT1 PD7 |
|||
|
|||
|
|||
choice 'Column Port 1 (right)' \ |
|||
"PORTA PORTA \ |
|||
PORTB PORTB \ |
|||
PORTC PORTC \ |
|||
PORTD PORTD" \ |
|||
'PORTC' COLPORT1 |
|||
|
|||
choice 'Column Port 2 (left)' \ |
|||
"PORTA PORTA \ |
|||
PORTB PORTB \ |
|||
PORTC PORTC \ |
|||
PORTD PORTD" \ |
|||
'PORTA' COLPORT2 |
|||
|
|||
choice 'port for row shiftregisters' \ |
|||
"PORTA PORTA \ |
|||
PORTB PORTB \ |
|||
PORTC PORTC \ |
|||
PORTD PORTD" \ |
|||
'PORTD' ROWPORT |
|||
|
|||
comment "pin numbers on shiftregister port" |
|||
|
|||
choice '/MCLR Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin4' PIN_MCLR |
|||
|
|||
choice 'CLK Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin6' PIN_CLK |
|||
|
|||
choice 'DATA Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin7' PIN_DATA |
|||
|
|||
endmenu |
@ -0,0 +1,55 @@ |
|||
mainmenu_option next_comment |
|||
comment "Laufschrift-Borg port setup" |
|||
|
|||
|
|||
choice 'port for row select' \ |
|||
"PORTA PORTA \ |
|||
PORTB PORTB \ |
|||
PORTC PORTC \ |
|||
PORTD PORTD" \ |
|||
'PORTB' ROWPORT |
|||
|
|||
|
|||
choice 'Column shiftregister Port' \ |
|||
"PORTA PORTA \ |
|||
PORTB PORTB \ |
|||
PORTC PORTC \ |
|||
PORTD PORTD" \ |
|||
'PORTD' COLPORT |
|||
|
|||
comment "pin numbers on shiftregister port" |
|||
|
|||
choice 'CLK Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin6' PIN_CLK |
|||
|
|||
choice 'DATA Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin4' PIN_DATA |
|||
|
|||
choice 'LINE_EN Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin5' PIN_LINE_EN |
|||
|
|||
endmenu |
@ -0,0 +1,50 @@ |
|||
mainmenu_option next_comment |
|||
comment "Borg-mini port setup" |
|||
|
|||
|
|||
choice 'Row Port 1' \ |
|||
"PORTA PORTA \ |
|||
PORTB PORTB \ |
|||
PORTC PORTC \ |
|||
PORTD PORTD" \ |
|||
'PORTD' ROWPORT1 |
|||
|
|||
choice 'Row Port 2' \ |
|||
"PORTA PORTA \ |
|||
PORTB PORTB \ |
|||
PORTC PORTC \ |
|||
PORTD PORTD" \ |
|||
'PORTC' ROWPORT2 |
|||
|
|||
choice 'Column shiftregister Port' \ |
|||
"PORTA PORTA \ |
|||
PORTB PORTB \ |
|||
PORTC PORTC \ |
|||
PORTD PORTD" \ |
|||
'PORTC' COLPORT |
|||
|
|||
comment "pin numbers on shiftregister port" |
|||
|
|||
choice 'CLK Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin5' PIN_CLK |
|||
|
|||
choice 'DATA Pin' \ |
|||
"Pin0 0 \ |
|||
Pin1 1 \ |
|||
Pin2 2 \ |
|||
Pin3 3 \ |
|||
Pin4 4 \ |
|||
Pin5 5 \ |
|||
Pin6 6 \ |
|||
Pin7 7" \ |
|||
'Pin4' PIN_DATA |
|||
|
|||
endmenu |
@ -0,0 +1,134 @@ |
|||
#include "can.h" |
|||
#include "lap.h" |
|||
#include "borg_can.h" |
|||
#include "spi.h" |
|||
#include "blinken.h" |
|||
|
|||
#include <avr/pgmspace.h> |
|||
#include <setjmp.h> |
|||
#include <avr/interrupt.h> |
|||
#include <avr/eeprom.h> |
|||
#include <string.h> |
|||
|
|||
can_addr myaddr; |
|||
extern jmp_buf newmode_jmpbuf; |
|||
|
|||
void bcan_init() |
|||
{ |
|||
spi_init(); |
|||
can_init(); |
|||
|
|||
myaddr = eeprom_read_byte(0x00); |
|||
pdo_message *msg = (pdo_message *)can_buffer_get(); |
|||
msg->addr_src = myaddr; |
|||
msg->addr_dst = 0xff; |
|||
msg->port_src = PORT_BORG; |
|||
msg->port_dst = PORT_BORG; |
|||
msg->dlc = 4; |
|||
msg->cmd = FKT_BORG_INFO; |
|||
msg->data[0] = NUM_ROWS; |
|||
msg->data[1] = NUM_COLS; |
|||
msg->data[2] = NUM_PLANES; |
|||
|
|||
can_transmit((can_message *)msg); |
|||
} |
|||
|
|||
void process_mgt_msg(pdo_message *msg) |
|||
{ |
|||
pdo_message *rmsg; |
|||
|
|||
switch(msg->cmd) { |
|||
case FKT_MGT_RESET: |
|||
timer0_off(); |
|||
cli(); |
|||
while(1); |
|||
break; |
|||
case FKT_MGT_PING: |
|||
rmsg = (pdo_message *)can_buffer_get(); |
|||
rmsg->addr_dst = msg->addr_src; |
|||
rmsg->addr_src = myaddr; |
|||
rmsg->port_dst = msg->port_src; |
|||
rmsg->port_src = msg->port_dst; |
|||
rmsg->cmd = FKT_MGT_PONG; |
|||
rmsg->dlc = 1; |
|||
can_transmit((can_message *)rmsg); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void process_borg_msg(pdo_message *msg) |
|||
{ |
|||
unsigned char i, j; |
|||
|
|||
switch(msg->cmd) { |
|||
case FKT_BORG_MODE: |
|||
longjmp(newmode_jmpbuf, msg->data[0]); |
|||
break; |
|||
case FKT_BORG_SCROLLTEXT_RESET: |
|||
for(i=0; i < msg->dlc-1; i++) { |
|||
scrolltext_text[i] = msg->data[i]; |
|||
} |
|||
scrolltext_text[i] = 0; |
|||
|
|||
break; |
|||
case FKT_BORG_SCROLLTEXT_APPEND: |
|||
j=0; |
|||
while(scrolltext_text[j]) j++; |
|||
|
|||
for(i=0; i < msg->dlc-1; i++) { |
|||
scrolltext_text[i+j] = msg->data[i]; |
|||
} |
|||
scrolltext_text[i+j] = 0; |
|||
|
|||
break; |
|||
|
|||
#ifdef Hansi_hat_gelernt_Werte_vorher_zu_definieren |
|||
|
|||
//========== blinkenstuff
|
|||
|
|||
//clear the blinkenbackbuffer to color
|
|||
case FKT_BLINK_CLEARBUF: |
|||
blink_clearbuf(msg->data[0]); |
|||
break; |
|||
|
|||
//set auto position increment flag
|
|||
case FKT_BLINK_SETAUTOPOS: |
|||
blink_setautopos(msg->data[0]); |
|||
break; |
|||
|
|||
//set the current blinkenbuffer offset position
|
|||
case FKT_BLINK_SETPOS: |
|||
blink_setpos(msg->data[0]); |
|||
break; |
|||
|
|||
//puts the current blinkenbuffer to the frontbuffer
|
|||
case FKT_BLINK_SHOW: |
|||
blink_show(); |
|||
break; |
|||
|
|||
//puts data into the blinkenbuffer
|
|||
case FKT_BLINK_DATA: |
|||
blink_data(msg->data, msg->dlc - 1); |
|||
break; |
|||
#endif |
|||
} |
|||
} |
|||
|
|||
void bcan_process_messages() |
|||
{ |
|||
pdo_message *msg = (pdo_message*) can_get_nb(); |
|||
|
|||
while(msg) { |
|||
if (!msg) |
|||
return; |
|||
|
|||
if(msg->addr_dst == myaddr && msg->port_dst == PORT_MGT) |
|||
process_mgt_msg(msg); |
|||
|
|||
if(msg->addr_dst == myaddr && msg->port_dst == PORT_BORG) |
|||
process_borg_msg(msg); |
|||
|
|||
msg = (pdo_message*) can_get_nb(); |
|||
}; |
|||
|
|||
} |
@ -0,0 +1,11 @@ |
|||
#ifndef BORG_CAN_H_ |
|||
#define BORG_CAN_H_ |
|||
|
|||
extern unsigned char borg_mode; |
|||
extern char scrolltext_text[]; |
|||
|
|||
void bcan_init(); |
|||
unsigned char bcan_mode(); |
|||
void bcan_process_messages(); |
|||
|
|||
#endif /* BORG_CAN_H */ |
@ -0,0 +1,496 @@ |
|||
|
|||
#ifndef __C64__ |
|||
#include <avr/io.h> |
|||
#include <avr/interrupt.h> |
|||
#define asm asm volatile |
|||
#endif |
|||
|
|||
#include "can.h" |
|||
#include "spi.h" |
|||
|
|||
#define spi_clear_ss() SPI_PORT |= (1<<SPI_PIN_SS) |
|||
#define spi_set_ss() SPI_PORT &= ~(1<<SPI_PIN_SS) |
|||
|
|||
//Registers
|
|||
#define RXF0SIDH 0x00 |
|||
#define RXF0SIDL 0x01 |
|||
#define RXF0EID8 0x02 |
|||
#define RXF0EID0 0x03 |
|||
#define RXF1SIDH 0x04 |
|||
#define RXF1SIDL 0x05 |
|||
#define RXF1EID8 0x06 |
|||
#define RXF1EID0 0x07 |
|||
#define RXF2SIDH 0x08 |
|||
#define RXF2SIDL 0x09 |
|||
#define RXF2EID8 0x0A |
|||
#define RXF2EID0 0x0B |
|||
#define BFPCTRL 0x0C |
|||
#define TXRTSCTRL 0x0D |
|||
#define CANSTAT 0x0E |
|||
#define CANCTRL 0x0F |
|||
#define RXF3SIDH 0x10 |
|||
#define RXF3SIDL 0x11 |
|||
#define RXF3EID8 0x12 |
|||
#define RXF3EID0 0x13 |
|||
#define RXF4SIDH 0x14 |
|||
#define RXF4SIDL 0x15 |
|||
#define RXF4EID8 0x16 |
|||
#define RXF4EID0 0x17 |
|||
#define RXF5SIDH 0x18 |
|||
#define RXF5SIDL 0x19 |
|||
#define RXF5EID8 0x1A |
|||
#define RXF5EID0 0x1B |
|||
#define TEC 0x1C |
|||
#define REC 0x1D |
|||
#define RXM0SIDH 0x20 |
|||
#define RXM0SIDL 0x21 |
|||
#define RXM0EID8 0x22 |
|||
#define RXM0EID0 0x23 |
|||
#define RXM1SIDH 0x24 |
|||
#define RXM1SIDL 0x25 |
|||
#define RXM1EID8 0x26 |
|||
#define RXM1EID0 0x27 |
|||
#define CNF3 0x28 |
|||
#define CNF2 0x29 |
|||
#define CNF1 0x2A |
|||
#define CANINTE 0x2B |
|||
#define MERRE 7 |
|||
#define WAKIE 6 |
|||
#define ERRIE 5 |
|||
#define TX2IE 4 |
|||
#define TX1IE 3 |
|||
#define TX0IE 2 |
|||
#define RX1IE 1 |
|||
#define RX0IE 0 |
|||
#define CANINTF 0x2C |
|||
#define MERRF 7 |
|||
#define WAKIF 6 |
|||
#define ERRIF 5 |
|||
#define TX2IF 4 |
|||
#define TX1IF 3 |
|||
#define TX0IF 2 |
|||
#define RX1IF 1 |
|||
#define RX0IF 0 |
|||
#define EFLG 0x2D |
|||
#define TXB0CTRL 0x30 |
|||
#define TXREQ 3 |
|||
#define TXB0SIDH 0x31 |
|||
#define TXB0SIDL 0x32 |
|||
#define EXIDE 3 |
|||
#define TXB0EID8 0x33 |
|||
#define TXB0EID0 0x34 |
|||
#define TXB0DLC 0x35 |
|||
#define TXB0D0 0x36 |
|||
|
|||
#define RXB0CTRL 0x60 |
|||
#define RXM1 6 |
|||
#define RXM0 5 |
|||
#define RXRTR 3 |
|||
// Bits 2:0 FILHIT2:0
|
|||
#define RXB0SIDH 0x61 |
|||
#define RXB0SIDL 0x62 |
|||
#define RXB0EID8 0x63 |
|||
#define RXB0EID0 0x64 |
|||
#define RXB0DLC 0x65 |
|||
#define RXB0D0 0x66 |
|||
|
|||
//Command Bytes
|
|||
#define RESET 0xC0 |
|||
#define READ 0x03 |
|||
#define READ_RX_BUFFER 0x90 |
|||
#define WRITE 0x02 |
|||
#define LOAD_TX_BUFFER 0x40 |
|||
#define RTS 0x80 |
|||
#define READ_STATUS 0xA0 |
|||
#define RX_STATUS 0xB0 |
|||
#define BIT_MODIFY 0x05 |
|||
|
|||
typedef struct{ |
|||
can_message msg; |
|||
volatile unsigned char flags; |
|||
}can_message_x; |
|||
|
|||
|
|||
/* MCP */ |
|||
void mcp_reset(); |
|||
void mcp_write(unsigned char reg, unsigned char data); |
|||
//void mcp_write_b(unsigned char reg, unsigned char *buf, unsigned char len);
|
|||
unsigned char mcp_read(unsigned char reg); |
|||
//void mcp_read_b(unsigned char reg, unsigned char *buf, unsigned char len);
|
|||
void mcp_bitmod(unsigned char reg, unsigned char mask, unsigned char val); |
|||
unsigned char mcp_status(); |
|||
//unsigned char mcp_rx_status();
|
|||
|
|||
// Functions
|
|||
/*
|
|||
unsigned char mcp_rx_status(){ |
|||
unsigned char d; |
|||
spi_set_ss(); |
|||
spi_data(RX_STATUS); |
|||
d = spi_data(0); |
|||
spi_clear_ss(); |
|||
return d; |
|||
} |
|||
*/ |
|||
|
|||
unsigned char mcp_status(){ |
|||
unsigned char d; |
|||
spi_set_ss(); |
|||
spi_data(READ_STATUS); |
|||
d = spi_data(0); |
|||
spi_clear_ss(); |
|||
return d; |
|||
} |
|||
|
|||
void mcp_bitmod(unsigned char reg, unsigned char mask, unsigned char val){ |
|||
spi_set_ss(); |
|||
spi_data(BIT_MODIFY); |
|||
spi_data(reg); |
|||
spi_data(mask); |
|||
spi_data(val); |
|||
spi_clear_ss(); |
|||
} |
|||
|
|||
//load a message to mcp2515 and start transmission
|
|||
void message_load(can_message_x * msg){ |
|||
unsigned char x; |
|||
|
|||
spi_set_ss(); |
|||
spi_data(WRITE); |
|||
spi_data(TXB0SIDH); |
|||
|
|||
spi_data( ((unsigned char)(msg->msg.port_src << 2)) | (msg->msg.port_dst >> 4 ) ); |
|||
spi_data( (unsigned char)((msg->msg.port_dst & 0x0C) << 3) | (1<<EXIDE) | (msg->msg.port_dst & 0x03) ); |
|||
spi_data(msg->msg.addr_src); |
|||
spi_data(msg->msg.addr_dst); |
|||
spi_data(msg->msg.dlc); |
|||
for(x=0;x<msg->msg.dlc;x++){ |
|||
spi_data(msg->msg.data[x]); |
|||
} |
|||
spi_clear_ss(); |
|||
spi_set_ss(); |
|||
spi_data(WRITE); |
|||
spi_data(TXB0CTRL); |
|||
spi_data( (1<<TXREQ) ); |
|||
spi_clear_ss(); |
|||
} |
|||
|
|||
//get a message from mcp2515 and disable RX interrupt Condition
|
|||
void message_fetch(can_message_x * msg){ |
|||
unsigned char tmp1, tmp2, tmp3; |
|||
unsigned char x; |
|||
|
|||
spi_set_ss(); |
|||
spi_data(READ); |
|||
spi_data(RXB0SIDH); |
|||
tmp1 = spi_data(0); |
|||
msg->msg.port_src = tmp1 >> 2; |
|||
tmp2 = spi_data(0); |
|||
tmp3 = (unsigned char)((unsigned char)(tmp2 >> 3) & 0x0C); |
|||
msg->msg.port_dst = ((unsigned char)(tmp1 <<4 ) & 0x30) | tmp3 | (unsigned char)(tmp2 & 0x03); |
|||
msg->msg.addr_src = spi_data(0); |
|||
msg->msg.addr_dst = spi_data(0); |
|||
msg->msg.dlc = spi_data(0) & 0x0F; |
|||
for(x=0;x<msg->msg.dlc;x++){ |
|||
msg->msg.data[x] = spi_data(0); |
|||
} |
|||
spi_clear_ss(); |
|||
|
|||
mcp_bitmod(CANINTF, (1<<RX0IF), 0x00); |
|||
} |
|||
#ifdef CAN_INTERRUPT |
|||
|
|||
static can_message_x RX_BUFFER[CAN_RX_BUFFER_SIZE], TX_BUFFER[CAN_TX_BUFFER_SIZE]; |
|||
unsigned char RX_HEAD=0;volatile unsigned char RX_TAIL=0; |
|||
unsigned char TX_HEAD= 0;volatile unsigned char TX_TAIL=0; |
|||
static volatile unsigned char TX_INT; |
|||
|
|||
SIGNAL(SIG_INTERRUPT0) { |
|||
unsigned char status = mcp_status(); |
|||
|
|||
if ( status & 0x01 ) { // Message in RX0
|
|||
if ( !(((can_message_x*)&RX_BUFFER[RX_HEAD])->flags & 0x01) ) { |
|||
message_fetch(&RX_BUFFER[RX_HEAD]); |
|||
RX_BUFFER[RX_HEAD].flags |= 0x01;//mark buffer as used
|
|||
if( ++RX_HEAD == CAN_RX_BUFFER_SIZE) RX_HEAD = 0; |
|||
}else{ |
|||
//buffer overflow
|
|||
//just clear the Interrupt condition, and lose the message
|
|||
mcp_bitmod(CANINTF, (1<<RX0IF), 0x00); |
|||
} |
|||
} else if ( status & 0x08 ) { // TX1 empty
|
|||
if(((can_message_x*)&TX_BUFFER[TX_TAIL])->flags & 0x01) { |
|||
((can_message_x*)&TX_BUFFER[TX_TAIL])->flags &= ~0x01; |
|||
TX_INT = 1; |
|||
message_load(&TX_BUFFER[TX_TAIL]); |
|||
if(++TX_TAIL == CAN_TX_BUFFER_SIZE) TX_TAIL = 0; |
|||
}else{ |
|||
TX_INT = 0; |
|||
} |
|||
mcp_bitmod(CANINTF, (1<<TX0IF), 0x00); |
|||
} else { |
|||
#ifdef CAN_HANDLEERROR |
|||
status = mcp_read(EFLG); |
|||
|
|||
if(status) { // we've got a error condition
|
|||
can_error = status; |
|||
|
|||
mcp_write(EFLG, 0); |
|||
} |
|||
#endif // CAN_HANDLEERROR
|
|||
} |
|||
} |
|||
|
|||
#endif |
|||
|
|||
|
|||
void mcp_reset(){ |
|||
spi_set_ss(); |
|||
spi_data(RESET); |
|||
spi_clear_ss(); |
|||
} |
|||
|
|||
void mcp_write(unsigned char reg, unsigned char data){ |
|||
spi_set_ss(); |
|||
spi_data(WRITE); |
|||
spi_data(reg); |
|||
spi_data(data); |
|||
spi_clear_ss(); |
|||
} |
|||
|
|||
/*
|
|||
void mcp_write_b(unsigned char reg, unsigned char *buf, unsigned char len){ |
|||
unsigned char x; |
|||
spi_set_ss(); |
|||
spi_data(WRITE); |
|||
spi_data(reg); |
|||
for(x=0;x<len;x++){ |
|||
spi_data(buf[x]); |
|||
} |
|||
spi_clear_ss(); |
|||
} |
|||
*/ |
|||
|
|||
unsigned char mcp_read(unsigned char reg){ |
|||
unsigned char d; |
|||
spi_set_ss(); |
|||
spi_data(READ); |
|||
spi_data(reg); |
|||
d = spi_data(0); |
|||
spi_clear_ss(); |
|||
return d; |
|||
} |
|||
|
|||
/*
|
|||
void mcp_read_b(unsigned char reg, unsigned char *buf, unsigned char len){ |
|||
unsigned char x; |
|||
spi_set_ss(); |
|||
spi_data(READ); |
|||
spi_data(reg); |
|||
for(x=0;x<len;x++){ |
|||
buf[x] = spi_data(0); |
|||
} |
|||
spi_clear_ss(); |
|||
} |
|||
*/ |
|||
|
|||
|
|||
/* Management */ |
|||
void can_setmode( can_mode_t mode ) { |
|||
unsigned char val = mode << 5; |
|||
val |= 0x04; // CLKEN
|
|||
|
|||
mcp_write( CANCTRL, val ); |
|||
} |
|||
|
|||
|
|||
void can_setfilter() { |
|||
//RXM1 RXM0
|
|||
// 0 0 receive matching filter
|
|||
// 0 1 " only 11bit Identifier
|
|||
// 1 0 " only 29bit Identifier
|
|||
// 1 1 any
|
|||
mcp_write(RXB0CTRL, (1<<RXM1) | (1<<RXM0)); |
|||
} |
|||
|
|||
void can_setled(unsigned char led, unsigned char state){ |
|||
mcp_bitmod(BFPCTRL, 0x10<<led, state?0xff:0); |
|||
} |
|||
|
|||
/*******************************************************************/ |
|||
void delayloop(){ |
|||
unsigned char x; |
|||
for(x=0;x<255;x++){ |
|||
asm ("nop"); |
|||
} |
|||
|
|||
} |
|||
|
|||
void can_init(){ |
|||
//set Slave select high
|
|||
SPI_PORT |= (1<<SPI_PIN_SS); |
|||
|
|||
#ifdef CAN_INTERRUPT |
|||
unsigned char x; |
|||
for(x=0;x<CAN_RX_BUFFER_SIZE;x++){ |
|||
RX_BUFFER[x].flags = 0; |
|||
} |
|||
for(x=0;x<CAN_TX_BUFFER_SIZE;x++){ |
|||
TX_BUFFER[x].flags = 0; |
|||
} |
|||
|
|||
#endif |
|||
|
|||
#ifdef CAN_HANDLEERROR |
|||
can_error = 0; |
|||
#endif |
|||
|
|||
mcp_reset(); |
|||
|
|||
delayloop(); |
|||
|
|||
mcp_write(BFPCTRL,0x0C);//RXBF Pins to Output
|
|||
|
|||
// 0x01 : 125kbit/8MHz
|
|||
// 0x03 : 125kbit/16MHz
|
|||
// 0x04 : 125kbit/20MHz
|
|||
|
|||
#if F_MCP == 16000000 |
|||
#define CNF1_T 0x03 |
|||
#elif F_MCP == 8000000 |
|||
#define CNF1_T 0x01 |
|||
#elif F_MCP == 20000000 |
|||
#define CNF1_T 0x04 |
|||
#else |
|||
#error Can Baudrate is only defined for 8, 16 and 20 MHz |
|||
#endif |
|||
mcp_write( CNF1, 0x40 | CNF1_T ); |
|||
mcp_write( CNF2, 0xf1 ); |
|||
mcp_write( CNF3, 0x05 ); |
|||
|
|||
// configure IRQ
|
|||
// this only configures the INT Output of the mcp2515, not the int on the Atmel
|
|||
mcp_write( CANINTE, (1<<RX0IE) | (1<<TX0IE) ); |
|||
|
|||
can_setfilter(); |
|||
can_setmode(normal); |
|||
|
|||
#ifdef CAN_INTERRUPT |
|||
|
|||
// configure IRQ
|
|||
// this only configures the INT Output of the mcp2515, not the int on the Atmel
|
|||
mcp_write( CANINTE, (1<<RX0IE) | (1<<TX0IE) ); |
|||
|
|||
|
|||
#ifdef __C64__ |
|||
#error not implemented yet |
|||
#elif ATMEGA |
|||
//this turns on INT0 on the Atmega
|
|||
GICR |= (1<<INT0); |
|||
#else |
|||
//this turns on INT0 on the Atmel
|
|||
MCUCR |= (1<<ISC01); |
|||
GIMSK |= (1<<INT0); |
|||
#endif //ATMEGA
|
|||
|
|||
#else //CAN_INTERRUPT
|
|||
// configure IRQ
|
|||
// this only configures the INT Output of the mcp2515, not the int on the Atmel
|
|||
mcp_write( CANINTE, (1<<RX0IE) ); //only turn RX int on
|
|||
#endif //CAN_INTERRUPT
|
|||
} |
|||
|
|||
#ifdef CAN_INTERRUPT |
|||
//returns next can message in buffer, or 0 Pointer if buffer is empty
|
|||
can_message * can_get_nb(){ |
|||
can_message_x *p; |
|||
if(RX_HEAD == RX_TAIL){ |
|||
return 0; |
|||
}else{ |
|||
p = &RX_BUFFER[RX_TAIL]; |
|||
if(++RX_TAIL == CAN_RX_BUFFER_SIZE) RX_TAIL = 0; |
|||
return &(p->msg); |
|||
} |
|||
} |
|||
|
|||
can_message * can_get(){ |
|||
can_message_x *p; |
|||
|
|||
while(RX_HEAD == RX_TAIL) { }; |
|||
|
|||
p = &RX_BUFFER[RX_TAIL]; |
|||
if(++RX_TAIL == CAN_RX_BUFFER_SIZE) RX_TAIL = 0; |
|||
|
|||
return &(p->msg); |
|||
} |
|||
|
|||
|
|||
//marks a receive buffer as unused again so it can be overwritten in Interrupt
|
|||
void can_free(can_message * msg){ |
|||
can_message_x * msg_x = (can_message_x *) msg; |
|||
msg_x->flags = 0; |
|||
} |
|||
|
|||
|
|||
//returns pointer to the next can TX buffer
|
|||
can_message * can_buffer_get(){ |
|||
can_message_x *p; |
|||
p = &TX_BUFFER[TX_HEAD]; |
|||
while (p->flags&0x01); //wait until buffer is free
|
|||
if(++TX_HEAD == CAN_TX_BUFFER_SIZE) TX_HEAD = 0; |
|||
return &(p->msg); |
|||
} |
|||
|
|||
|
|||
//start transmitting can messages, and mark message msg as transmittable
|
|||
void can_transmit(can_message* msg2){ |
|||
can_message_x* msg=(can_message_x*) msg2; |
|||
if(msg){ |
|||
msg->flags |= 0x01; |
|||
} |
|||
if(!TX_INT){ |
|||
if(((can_message_x*)&TX_BUFFER[TX_TAIL])->flags & 0x01){ |
|||
((can_message_x*)&TX_BUFFER[TX_TAIL])->flags &= ~0x01; |
|||
TX_INT = 1; |
|||
message_load(&TX_BUFFER[TX_TAIL]); |
|||
if(++TX_TAIL == CAN_TX_BUFFER_SIZE) TX_TAIL = 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
#else // NON INTERRUPT VERSION
|
|||
|
|||
can_message_x RX_MESSAGE, TX_MESSAGE; |
|||
|
|||
can_message * can_get_nb(){ |
|||
//check the pin, that the MCP's Interrup output connects to
|
|||
if(SPI_REG_PIN_MCP_INT & (1<<SPI_PIN_MCP_INT)){ |
|||
return 0; |
|||
}else{ |
|||
//So the MCP Generates an RX Interrupt
|
|||
message_fetch(&RX_MESSAGE); |
|||
return &(RX_MESSAGE.msg); |
|||
} |
|||
} |
|||
|
|||
can_message * can_get(){ |
|||
//wait while the MCP doesn't generate an RX Interrupt
|
|||
while(SPI_REG_PIN_MCP_INT & (1<<SPI_PIN_MCP_INT)) { }; |
|||
|
|||
message_fetch(&RX_MESSAGE); |
|||
return &(RX_MESSAGE.msg); |
|||
} |
|||
|
|||
//only for compatibility with Interrupt driven Version
|
|||
can_message * can_buffer_get(){ |
|||
return &(TX_MESSAGE.msg); |
|||
} |
|||
|
|||
void can_transmit(can_message * msg){ |
|||
message_load((can_message_x*)msg); |
|||
} |
|||
|
|||
void can_free(can_message * msg){ |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,139 @@ |
|||
#ifndef CAN_H |
|||
#define CAN_H |
|||
|
|||
/*****************************************************************************
|
|||
* Simple CAN Library |
|||
* |
|||
* #define CAN_INTERRUPT 1 //set this to enable interrupt driven
|
|||
* and buffering version |
|||
* #define CAN_RX_BUFFER_SIZE 2 //only used for Interrupt
|
|||
* #define CAN_TX_BUFFER_SIZE 2 //only used for Interrupt
|
|||
*/ |
|||
|
|||
/*****************************************************************************
|
|||
* Types |
|||
*/ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
typedef unsigned char can_addr; |
|||
typedef unsigned char can_port; |
|||
typedef uint16_t can_channel_t; |
|||
typedef uint8_t can_subchannel_t; |
|||
|
|||
typedef struct |
|||
{ |
|||
uint32_t id; |
|||
uint8_t dlc; |
|||
uint8_t data[8]; |
|||
} can_message_raw; |
|||
|
|||
typedef struct{ |
|||
can_addr addr_src; |
|||
can_addr addr_dst; |
|||
can_port port_src; |
|||
can_port port_dst; |
|||
unsigned char dlc; |
|||
unsigned char data[8]; |
|||
}can_message; |
|||
|
|||
typedef struct |
|||
{ |
|||
can_channel_t channel; |
|||
can_subchannel_t subchannel; |
|||
can_addr addr_src; |
|||
can_addr addr_dst; |
|||
uint8_t dlc; |
|||
uint8_t data[8]; |
|||
} can_message_v2; |
|||
|
|||
|
|||
typedef enum { normal, mode_sleep, loopback, listenonly, config } can_mode_t ; |
|||
|
|||
|
|||
/*****************************************************************************
|
|||
* Global variables |
|||
*/ |
|||
#ifdef CAN_HANDLEERROR |
|||
extern unsigned char can_error; |
|||
#endif |
|||
|
|||
|
|||
/*****************************************************************************
|
|||
* Management |
|||
*/ |
|||
|
|||
void can_init(); |
|||
void can_setfilter(); |
|||
void can_setmode(can_mode_t); |
|||
void can_setled(unsigned char led, unsigned char state); |
|||
|
|||
|
|||
/*****************************************************************************
|
|||
* Sending |
|||
*/ |
|||
|
|||
can_message * can_buffer_get(); |
|||
void can_transmit( can_message *msg ); |
|||
|
|||
|
|||
/*****************************************************************************
|
|||
* Receiving |
|||
*/ |
|||
|
|||
can_message *can_get(); |
|||
can_message *can_get_nb(); |
|||
|
|||
// this is only needed for Interrupt driven Version
|
|||
#ifndef CAN_INTERRUPT |
|||
// # define can_free(m)
|
|||
void can_free(can_message * msg); |
|||
#else |
|||
void can_free(can_message * msg); |
|||
#endif |
|||
|
|||
|
|||
/*****************************************************************************
|
|||
* Sending |
|||
*/ |
|||
|
|||
can_message_raw * can_buffer_get_raw(); |
|||
void can_transmit_raw( can_message_raw *msg ); |
|||
|
|||
|
|||
/*****************************************************************************
|
|||
* Receiving |
|||
*/ |
|||
|
|||
can_message_raw *can_get_raw(); |
|||
can_message_raw *can_get_raw_nb(); |
|||
|
|||
// this is only needed for Interrupt driven Version
|
|||
#ifndef CAN_INTERRUPT |
|||
// # define can_free(m)
|
|||
void can_free_raw(can_message_raw * msg); |
|||
#else |
|||
void can_free_raw(can_message_raw * msg); |
|||
#endif |
|||
|
|||
|
|||
|
|||
|
|||
/*****************************************************************************
|
|||
* Sending |
|||
*/ |
|||
|
|||
void can_transmit_v2( can_message_v2 *msg ); |
|||
|
|||
|
|||
/*****************************************************************************
|
|||
* Receiving |
|||
*/ |
|||
|
|||
can_message_v2 *can_get_v2_nb(); |
|||
|
|||
void can_free_v2(can_message_v2 *msg); |
|||
|
|||
|
|||
|
|||
#endif |
@ -0,0 +1,55 @@ |
|||
#include <avr/io.h> |
|||
#include "spi.h" |
|||
|
|||
|
|||
void spi_init(){ |
|||
//set output SPI pins to output
|
|||
SPI_DDR |= (1<<SPI_PIN_MOSI) | (1<<SPI_PIN_SCK) | (1<<SPI_PIN_SS); |
|||
|
|||
#ifdef SPI_HARDWARE |
|||
// 0 1
|
|||
//DORD msb first lsb first
|
|||
//CPOL low idle high idle
|
|||
//CPHA rising edge fallling edge
|
|||
|
|||
//SPR0 SPR1
|
|||
// 0 0 ck/4
|
|||
// 0 1 ck/16
|
|||
// 1 0 ck/64
|
|||
// 1 1 ck/128
|
|||
|
|||
//Interrupt disable, SPI enable, MSB first, master, clk low idle, data valid on rising edge, ck/4
|
|||
SPCR = (0<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0); |
|||
|
|||
//Double speed on
|
|||
SPSR = (1<<SPI2X); |
|||
#endif |
|||
} |
|||
|
|||
#ifndef SPI_HARDWARE |
|||
unsigned char spi_data(unsigned char c){ |
|||
unsigned char x, d=d; |
|||
for(x=0;x<8;x++){ |
|||
if(c & 0x80){ |
|||
SPI_PORT |= (1<<SPI_PIN_MOSI); |
|||
}else{ |
|||
SPI_PORT &= ~(1<<SPI_PIN_MOSI); |
|||
} |
|||
SPI_PORT |= (1<<SPI_PIN_SCK); |
|||
d<<=1; |
|||
if(SPI_PIN & (1<<SPI_PIN_MISO)){ |
|||
d|=1; |
|||
} |
|||
SPI_PORT &= ~(1<<SPI_PIN_SCK); |
|||
c<<=1; |
|||
} |
|||
return d; |
|||
} |
|||
#else |
|||
unsigned char spi_data(unsigned char c) { |
|||
SPDR = c; |
|||
while(!(SPSR & (1<<SPIF))); |
|||
c = SPDR; |
|||
return (c); |
|||
} |
|||
#endif |
@ -0,0 +1,28 @@ |
|||
#ifndef SPI_H |
|||
#define SPI_H |
|||
|
|||
#include "config.h" |
|||
|
|||
/**
|
|||
* this enables the use of Hardware SPI on ATMEGA |
|||
* |
|||
* #define SPI_HARDWARE 1 |
|||
* #define SPI_PORT PORTB |
|||
* #define SPI_PIN PINB |
|||
* #define SPI_DDR DDRB |
|||
* |
|||
* #define SPI_PIN_MOSI PB5 |
|||
* #define SPI_PIN_MISO PB6 |
|||
* #define SPI_PIN_SCK PB7 |
|||
* #define SPI_PIN_SS PB4 |
|||
* |
|||
*/ |
|||
|
|||
|
|||
void spi_init(); |
|||
|
|||
unsigned char spi_data(unsigned char c); |
|||
|
|||
|
|||
|
|||
#endif |
@ -0,0 +1,57 @@ |
|||
#ifndef CONFIG_H_ |
|||
#define CONFIG_H_ |
|||
|
|||
#include "autoconf.h" |
|||
|
|||
#define STREAMER_NUM 30 |
|||
|
|||
#define FEUER_N 5 |
|||
#define FEUER_S 30 |
|||
#define FEUER_DIV 44 |
|||
#define FEUER_DELAY 50 |
|||
|
|||
#define SNAKE_DELAY 100 |
|||
|
|||
//#define SCROLLTEXT_STRING_SIZE 128
|
|||
//#define SCROLLTEXT_FONT font_arial8
|
|||
//#define SCROLLTEXT_DEFAULT "</#www.das-labor.org"
|
|||
//#define SCROLL_X_SPEED 20
|
|||
//#define SCROLL_Y_SPEED 20
|
|||
|
|||
#define BORG_CAN |
|||
|
|||
// spi.[ch] defines
|
|||
#define SPI_HARDWARE |
|||
#define SPI_PORT PORTB //for slave select
|
|||
#define SPI_PIN PINB //for slave select
|
|||
#define SPI_DDR DDRB |
|||
|
|||
#define SPI_PIN_MOSI PB5 |
|||
#define SPI_PIN_MISO PB6 |
|||
#define SPI_PIN_SCK PB7 |
|||
#define SPI_PIN_SS PB4 // for slave select
|
|||
|
|||
//interrupt pin of MCP2515 for non interrupt driven can
|
|||
#define SPI_REG_PIN_MCP_INT PIND |
|||
#define SPI_PIN_MCP_INT PD2 |
|||
|
|||
// can.[ch] defines
|
|||
#undef CAN_INTERRUPT //set this to enable interrupt driven and buffering version
|
|||
#define CAN_RX_BUFFER_SIZE 2 //only used for Interrupt
|
|||
#define CAN_TX_BUFFER_SIZE 2 //only used for Interrupt
|
|||
#define F_MCP F_CPU |
|||
|
|||
#define INIT_EEPROM |
|||
|
|||
//#define UART_BAUD_RATE 115200L
|
|||
|
|||
#define REVERSED_HARDWARE |
|||
//#define INVERSE_ROWS
|
|||
|
|||
//#define INTERLACED_ROWS
|
|||
//#define INTERLACED_COLS
|
|||
|
|||
|
|||
|
|||
|
|||
#endif /* CONFIG_H_ */ |
@ -0,0 +1,58 @@ |
|||
|
|||
mainmenu_name "Borg Configuration" |
|||
|
|||
###################### General Setup Menu ##################################### |
|||
mainmenu_option next_comment |
|||
comment "General Setup" |
|||
|
|||
#bool 'Prompt for experimental code' CONFIG_EXPERIMENTAL |
|||
|
|||
choice 'Target MCU' \ |
|||
"ATmega8 atmega8 \ |
|||
ATmega32 atmega32 \ |
|||
ATmega644 atmega644 \ |
|||
ATmega644p atmega644p" \ |
|||
'ATmega32' MCU |
|||
|
|||
int "MCU frequency" FREQ 16000000 |
|||
|
|||
|
|||
endmenu |
|||
############################################################################### |
|||
|
|||
###################### Borg Hardware Menu ##################################### |
|||
source borg_hw/config.in |
|||
############################################################################### |
|||
mainmenu_option next_comment |
|||
comment "Features" |
|||
|
|||
bool "prng random number generator" RANDOM_SUPPORT y |
|||
|
|||
endmenu |
|||
########################## Scrolltext Menu #################################### |
|||
source scrolltext/config.in |
|||
############################################################################### |
|||
|
|||
|
|||
|
|||
######################### Animations Menu ##################################### |
|||
mainmenu_option next_comment |
|||
comment "Animations" |
|||
comment "selects which animations are displayed in main loop" |
|||
|
|||
dep_bool "Scrolltext" ANIMATION_SCROLLTEXT $SCROLLTEXT_SUPPORT |
|||
bool "Spirale" ANIMATION_SPIRALE |
|||
bool "Joern1" ANIMATION_JOERN1 |
|||
bool "Snake" ANIMATION_SNAKE |
|||
bool "Schachbrett" ANIMATION_SCHACHBRETT |
|||
bool "Feuer" ANIMATION_FEUER |
|||
bool "Matrix" ANIMATION_MATRIX |
|||
bool "Random bright" ANIMATION_RANDOM_BRIGHT |
|||
bool "Game of Life" ANIMATION_GAMEOFLIFE |
|||
|
|||
comment "Special Animations" |
|||
bool "Test Animations" ANIMATION_TESTS |
|||
bool "Display off mode" ANIMATION_OFF |
|||
|
|||
endmenu |
|||
############################################################################### |
@ -0,0 +1,70 @@ |
|||
# ethersex project specific defaults, each can be overridden in config.mk
|
|||
F_CPU = 20000000UL |
|||
MCU = atmega644 |
|||
|
|||
CC=avr-gcc |
|||
AR=avr-ar |
|||
OBJCOPY = avr-objcopy |
|||
OBJDUMP = avr-objdump |
|||
AS = avr-as |
|||
CP = cp |
|||
RM = rm -f |
|||
AVRDUDE = avrdude |
|||
AVRDUDE_BAUDRATE = 115200 |
|||
SIZE = avr-size |
|||
STRIP = avr-strip |
|||
|
|||
HOSTCC := gcc |
|||
export HOSTCC |
|||
|
|||
# flags for the compiler
|
|||
CPPFLAGS += -mmcu=$(MCU) |
|||
CFLAGS ?= -Wall -W -Wno-unused-parameter -Wno-sign-compare |
|||
CFLAGS += -g -Os -std=gnu99 -fgnu89-inline |
|||
|
|||
# flags for the linker
|
|||
LDFLAGS += -mmcu=$(MCU) |
|||
|
|||
|
|||
##############################################################################
|
|||
# the default target
|
|||
$(TARGET): |
|||
|
|||
##############################################################################
|
|||
# include user's config.mk file
|
|||
|
|||
$(TOPDIR)/config.mk: |
|||
@echo "# Put your own config here!" > $@ |
|||
@echo "#F_CPU = $(F_CPU)" >> $@ |
|||
@echo "#MCU = $(MCU)" >> $@ |
|||
@echo "created default config.mk, tune your settings there!" |
|||
-include $(TOPDIR)/config.mk |
|||
|
|||
|
|||
##############################################################################
|
|||
# configure load address for bootloader, if enabled
|
|||
#
|
|||
ifneq ($(MAKECMDGOALS),clean) |
|||
ifneq ($(MAKECMDGOALS),mrproper) |
|||
ifneq ($(MAKECMDGOALS),menuconfig) |
|||
|
|||
include $(TOPDIR)/.config |
|||
|
|||
CPPFLAGS += -DF_CPU=$(FREQ)UL -mmcu=$(MCU) |
|||
|
|||
endif # MAKECMDGOALS!=menuconfig
|
|||
endif # MAKECMDGOALS!=mrproper
|
|||
endif # MAKECMDGOALS!=clean
|
|||
|
|||
ifeq ($(BOOTLOADER_SUPPORT),y) |
|||
LDFLAGS += -Wl,--section-start=.text=0xE000 |
|||
CFLAGS += -mcall-prologues |
|||
endif |
|||
|
|||
|
|||
%.s: %.c |
|||
$(CC) -o $@ -O0 $(CPPFLAGS) -S $< |
|||
|
|||
%.E: %.c |
|||
$(CC) -o $@ -O0 $(CPPFLAGS) -C -E -dD $< |
|||
|
@ -0,0 +1,32 @@ |
|||
# How to build automatic dependencies
|
|||
|
|||
# Don't include dependencies if $(no_deps) is set; the master makefile
|
|||
# does this for clean and other such targets that don't need
|
|||
# dependencies. That then avoids rebuilding dependencies.
|
|||
|
|||
ifneq ($(no_deps),t) |
|||
ifneq ($(MAKECMDGOALS),clean) |
|||
ifneq ($(MAKECMDGOALS),mrproper) |
|||
ifneq ($(MAKECMDGOALS),menuconfig) |
|||
|
|||
# For each .o file we need a .d file.
|
|||
-include $(subst .o,.d,$(filter %.o,$(OBJECTS))) /dev/null |
|||
|
|||
endif |
|||
endif |
|||
endif |
|||
endif |
|||
|
|||
# Here is how to build those dependency files
|
|||
|
|||
define make-deps |
|||
set -e; $(CC) $(CFLAGS) $(CPPFLAGS) -M -MM $< | \ |
|||
sed > $@.new -e 's;$(*F)\.o:;$@ $*.o $*.E $*.s:;' \ |
|||
-e 's% [^ ]*/gcc-lib/[^ ]*\.h%%g' |
|||
if test -s $@.new; then mv -f $@.new $@; else rm -f $@.new; fi |
|||
endef |
|||
|
|||
# Here is how to make .d files from .c files
|
|||
%.d: %.c $(TOPDIR)/pinning.c; $(make-deps) |
|||
|
|||
%.d: %.S ; $(make-deps) |
@ -0,0 +1,14 @@ |
|||
/*
|
|||
* |
|||
* |
|||
* |
|||
* |
|||
* |
|||
*/ |
|||
|
|||
#include <avr/eeprom.h> |
|||
#include <stdint.h> |
|||
|
|||
uint8_t EEMEM do_not_use; |
|||
|
|||
|
@ -0,0 +1,115 @@ |
|||
#include "invaders2.h" |
|||
/*----------------------getter/setter----------------------------*/ |
|||
|
|||
unsigned char getInvaderPixel(Invaders * iv, unsigned char x, unsigned char y) |
|||
{ |
|||
if (((x - iv->pos.x) < MAX_INVADER_WIDTH) && ((x - iv->pos.x) >= 0) && ((y |
|||
- iv->pos.y) < MAX_INVADER_HEIGHT) && ((y - iv->pos.y) >= 0)) |
|||
{ |
|||
return iv->map[x - iv->pos.x][y - iv->pos.y]; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
void setInvaderPixel(Invaders * iv, unsigned char x, unsigned char y, |
|||
unsigned char val) |
|||
{ |
|||
if (((x - iv->pos.x) < MAX_INVADER_WIDTH) && ((x - iv->pos.x) >= 0) && ((y |
|||
- iv->pos.y) < MAX_INVADER_HEIGHT) && ((y - iv->pos.y) >= 0)) |
|||
{ |
|||
iv->map[x - iv->pos.x][y - iv->pos.y] = val; |
|||
} |
|||
} |
|||
|
|||
unsigned char getGuardPixel(unsigned char guards[BORG_WIDTH], unsigned char x, |
|||
unsigned char y) |
|||
{ |
|||
if (x < BORG_WIDTH && y == GUARD_LINE) |
|||
return guards[x]; |
|||
return 0; |
|||
} |
|||
|
|||
void setGuardPixel(unsigned char guards[BORG_WIDTH], unsigned char x, |
|||
unsigned char y, unsigned char val) |
|||
{ |
|||
if (x < BORG_WIDTH && y == GUARD_LINE && val <= 3) |
|||
guards[x] = val; |
|||
} |
|||
|
|||
/*----------------------drawing Method---------------------------*/ |
|||
|
|||
void draw(Invaders * iv, Spaceship * sc, Player * pl, Cannon * cn, |
|||
unsigned char guards[BORG_WIDTH], uPixel st[MAX_SHOTS], uPixel * shot) |
|||
{ |
|||
clearScreen (); |
|||
|
|||
int x, y; |
|||
|
|||
/*---SPACESHIP---*/ |
|||
if (sc->pos < RIGHT_BORDER) |
|||
{ |
|||
setPixel (sc->pos, SPACESHIP_LINE, sc->lives); |
|||
} |
|||
if (sc->pos - 1 < RIGHT_BORDER) |
|||
{ |
|||
setPixel (sc->pos + 1, SPACESHIP_LINE, sc->lives); |
|||
} |
|||
|
|||
/*---INVADERS--*/ |
|||
for (y = 0; y < MAX_INVADER_HEIGHT; y++) |
|||
{ |
|||
for (x = 0; x < MAX_INVADER_WIDTH; x++) |
|||
{ |
|||
//mal in oder statement umwandeln ;-)
|
|||
if (iv->map[x][y] == 0) |
|||
continue; |
|||
if (x + iv->pos.x > RIGHT_BORDER) |
|||
continue; |
|||
if (x + iv->pos.x < 0) |
|||
continue; |
|||
|
|||
setPixel (x + iv->pos.x, y + iv->pos.y, iv->map[x][y]); |
|||
} |
|||
} |
|||
|
|||
/*---GUARDS---*/ |
|||
for (x = 0; x < BORG_WIDTH; ++x) |
|||
{ |
|||
if (guards[x] != 0) |
|||
{ |
|||
setPixel (x, GUARD_LINE, guards[x]); |
|||
} |
|||
} |
|||
|
|||
/*---SHOTS--*/ |
|||
int i; |
|||
for (i = 0; i < MAX_SHOTS; ++i) |
|||
{ |
|||
if (st[i].x < BORG_WIDTH && st[i].y < BORG_HEIGHT) |
|||
{ |
|||
setPixel (st[i].x, st[i].y, 3); |
|||
} |
|||
} |
|||
|
|||
/*draw player shot */ |
|||
if (!(cn->ready)) |
|||
{ |
|||
setPixel (shot->x, shot->y, 3); |
|||
} |
|||
|
|||
/*-- CANNON --*/ |
|||
if (cn->pos >= LEFT_BORDER + 1) |
|||
{ |
|||
setPixel (cn->pos - 1, 15, pl->lives); |
|||
} |
|||
if (cn->pos < BORG_WIDTH) |
|||
{ |
|||
setPixel (cn->pos, 15, pl->lives); |
|||
setPixel (cn->pos, 14, pl->lives); |
|||
} |
|||
if (cn->pos < RIGHT_BORDER) |
|||
{ |
|||
setPixel (cn->pos + 1, 15, pl->lives); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,153 @@ |
|||
#include "invaders2.h" |
|||
|
|||
unsigned char peter[8][11] = |
|||
{ |
|||
{ 0, 0, P, 0, 0, 0, 0, 0, P, 0, 0 }, |
|||
{ 0, 0, 0, P, 0, 0, 0, P, 0, 0, 0 }, |
|||
{ 0, 0, P, P, P, P, P, P, P, 0, 0 }, |
|||
{ 0, P, P, 0, P, P, P, 0, P, P, 0 }, |
|||
{ P, P, P, P, P, P, P, P, P, P, P }, |
|||
{ P, 0, P, P, P, P, P, P, P, 0, P }, |
|||
{ P, 0, P, 0, 0, 0, 0, 0, P, 0, P }, |
|||
{ 0, 0, 0, P, P, 0, P, P, 0, 0, 0 } }; |
|||
|
|||
unsigned char hans[8][11] = |
|||
{ |
|||
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, |
|||
{ 1, 2, 1, 1, 2, 2, 2, 1, 2, 2, 1 }, |
|||
{ 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2 }, |
|||
{ 1, 2, 1, 1, 2, 2, 2, 1, 2, 2, 1 }, |
|||
{ 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2 }, |
|||
{ 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 2 }, |
|||
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, |
|||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; |
|||
|
|||
void initGuards(unsigned char guards[BORG_WIDTH]) |
|||
{ |
|||
int x; |
|||
for (x = 0; x < BORG_WIDTH; ++x) |
|||
{ |
|||
guards[x] = 0; |
|||
} |
|||
|
|||
guards[3] = 3; |
|||
guards[6] = 3; |
|||
guards[10] = 3; |
|||
guards[13] = 3; |
|||
|
|||
} |
|||
|
|||
void initInvaders(Invaders * iv, unsigned char lv) |
|||
{ |
|||
unsigned char x, y; |
|||
|
|||
// first zero out map!
|
|||
for (x = 0; x < MAX_INVADER_WIDTH; ++x) |
|||
{ |
|||
for (y = 0; y < MAX_INVADER_HEIGHT; ++y) |
|||
{ |
|||
iv->map[x][y] = 0; |
|||
} |
|||
} |
|||
|
|||
iv->speedinc = 0; |
|||
iv->isEdged = 0; |
|||
|
|||
switch (lv) |
|||
{ |
|||
case 0: |
|||
for (x = 0; x < 8; ++x) |
|||
{ |
|||
iv->map[x][0] = 2; |
|||
iv->map[x][1] = 2; |
|||
iv->map[x][2] = 2; |
|||
iv->map[x][3] = 1; |
|||
// iv->map[x][4] = 1;
|
|||
} |
|||
|
|||
iv->pos.x = 4; |
|||
iv->pos.y = SPACESHIP_LINE + 1; |
|||
iv->speed = MIN_SPEED - 3; |
|||
iv->direction = 1; |
|||
break; |
|||
|
|||
case 1: |
|||
for (x = 0; x < 8; ++x) |
|||
{ |
|||
//for(y = 0; y < MAX_INVADER_HEIGHT; ++y) {
|
|||
iv->map[x][0] = 3; |
|||
iv->map[x][1] = 3; |
|||
iv->map[x][2] = 2; |
|||
iv->map[x][3] = 2; |
|||
// iv->map[x][4] = 1;
|
|||
//}
|
|||
} |
|||
|
|||
iv->pos.x = 4; |
|||
iv->pos.y = SPACESHIP_LINE + 1; |
|||
iv->speed = MIN_SPEED - 2; |
|||
|
|||
iv->direction = 1; |
|||
break; |
|||
|
|||
case 2: |
|||
for (x = 0; x < 8; ++x) |
|||
{ |
|||
//for(y = 0; y < MAX_INVADER_HEIGHT; ++y) {
|
|||
iv->map[x][0] = 3; |
|||
iv->map[x][1] = 3; |
|||
iv->map[x][2] = 2; |
|||
iv->map[x][3] = 2; |
|||
iv->map[x][4] = 1; |
|||
//}
|
|||
} |
|||
|
|||
iv->pos.x = 4; |
|||
iv->pos.y = SPACESHIP_LINE + 1; |
|||
iv->speed = MIN_SPEED - 1; |
|||
|
|||
iv->direction = 1; |
|||
break; |
|||
|
|||
case 3: |
|||
for (x = 0; x < 11; ++x) |
|||
{ |
|||
for (y = 0; y < 8; ++y) |
|||
{ |
|||
if (hans[y][x] != 0) |
|||
{ |
|||
iv->map[x][y] = 2; |
|||
} |
|||
} |
|||
} |
|||
|
|||
iv->pos.x = 3; |
|||
iv->pos.y = SPACESHIP_LINE + 1; |
|||
|
|||
iv->speed = MIN_SPEED + 2; |
|||
iv->direction = 1; |
|||
|
|||
break; |
|||
|
|||
case 4: |
|||
for (x = 0; x < 11; ++x) |
|||
{ |
|||
for (y = 0; y < 8; ++y) |
|||
{ |
|||
if (peter[y][x] != 0) |
|||
{ |
|||
iv->map[x][y] = 2; |
|||
} |
|||
} |
|||
} |
|||
|
|||
iv->pos.x = 3; |
|||
iv->pos.y = SPACESHIP_LINE + 1; |
|||
|
|||
iv->speed = MIN_SPEED + 3; |
|||
iv->direction = 1; |
|||
|
|||
break; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,304 @@ |
|||
#include <stdlib.h> |
|||
#include "prng.h" |
|||
#include "invaders2.h" |
|||
|
|||
void procCannon(Cannon * cn, uPixel * shot) |
|||
{ |
|||
static unsigned char mv = 0; |
|||
if (mv >= CANNON_SPEED) |
|||
{ |
|||
mv = 0; |
|||
if (JOYISLEFT) |
|||
{ |
|||
if (cn->pos != RIGHT_BORDER) |
|||
{ |
|||
cn->pos++; |
|||
} |
|||
} |
|||
else if (JOYISRIGHT) |
|||
{ |
|||
if (cn->pos != LEFT_BORDER) |
|||
{ |
|||
cn->pos--; |
|||
} |
|||
} |
|||
else if (JOYISFIRE) |
|||
{ |
|||
|
|||
if (cn->ready) |
|||
{ |
|||
shot->x = cn->pos; |
|||
shot->y = 14; |
|||
cn->ready = 0; |
|||
} |
|||
} |
|||
|
|||
} |
|||
else |
|||
{ |
|||
mv++; |
|||
} |
|||
|
|||
} |
|||
|
|||
unsigned char areAtBorder(Invaders * iv) |
|||
{ |
|||
int y; |
|||
for (y = SPACESHIP_LINE + 1; y <= GUARD_LINE; ++y) |
|||
{ |
|||
if (getInvaderPixel(iv, LEFT_BORDER, y) || getInvaderPixel(iv, |
|||
RIGHT_BORDER, y)) |
|||
{ |
|||
return 1; |
|||
} |
|||
} |
|||
return 0; |
|||
|
|||
} |
|||
|
|||
void procInvaders(Invaders * iv, uPixel st[MAX_SHOTS]) |
|||
{ |
|||
static unsigned char mv = 0; |
|||
|
|||
if (mv >= iv->speed) |
|||
{ |
|||
mv = 0; |
|||
if (areAtBorder(iv) && !(iv->isEdged)) |
|||
{ |
|||
iv->pos.y++; |
|||
iv->direction = -iv->direction; |
|||
iv->isEdged = 1; |
|||
} |
|||
else |
|||
{ |
|||
iv->pos.x += iv->direction; |
|||
iv->isEdged = 0; |
|||
} |
|||
|
|||
} |
|||
mv++; |
|||
|
|||
unsigned char i, y; |
|||
unsigned char spos = random8() % 16; |
|||
if (spos >= BORG_WIDTH) |
|||
return; |
|||
|
|||
unsigned char shoot = random8(); |
|||
|
|||
if (shoot < SHOOTING_RATE) |
|||
{ |
|||
for (i = 0; i < MAX_SHOTS; ++i) |
|||
{ |
|||
if (st[i].x > BORG_WIDTH || st[i].y > BORG_HEIGHT) |
|||
{ |
|||
|
|||
for (y = GUARD_LINE; y > SPACESHIP_LINE; --y) |
|||
{ |
|||
if (getInvaderPixel(iv, spos, y) != 0) |
|||
{ |
|||
|
|||
st[i].x = spos; |
|||
st[i].y = y + 1; |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
} //for SHOTS
|
|||
} |
|||
|
|||
} |
|||
|
|||
void procShots(Invaders * iv, Player * pl, Cannon * cn, Spaceship * sc, |
|||
unsigned char guards[BORG_WIDTH], uPixel st[MAX_SHOTS], uPixel * shot) |
|||
{ |
|||
|
|||
int i; |
|||
static unsigned char cmv = 0, imv = 0; |
|||
|
|||
// shuß mit einen struct mit dem shuß!!
|
|||
|
|||
if (cmv >= CANNON_SHOOTING_SPEED) |
|||
{ |
|||
cmv = 0; |
|||
if (!(cn->ready)) |
|||
{ |
|||
shot->y--; |
|||
} |
|||
if (shot->y > BORG_HEIGHT) |
|||
{ |
|||
cn->ready = 1; |
|||
} |
|||
} |
|||
|
|||
if (imv >= INVADER_SHOOTING_SPEED) |
|||
{ |
|||
imv = 0; |
|||
|
|||
for (i = 0; i < MAX_SHOTS; ++i) |
|||
{ |
|||
if ( /*st[i].x < BORG_WIDTH && */st[i].y < BORG_HEIGHT) |
|||
{ |
|||
st[i].y++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
cmv++; |
|||
imv++; |
|||
|
|||
/****************************************************************/ |
|||
/* TESTE OB GETROFFEN */ |
|||
/****************************************************************/ |
|||
|
|||
// USER CANNON
|
|||
|
|||
unsigned char tmp; |
|||
if (!(cn->ready)) |
|||
{ |
|||
for (i = 0; i < MAX_SHOTS; ++i) |
|||
{ |
|||
if (shot->x == st[i].x && shot->y == st[i].y) |
|||
{ |
|||
st[i].x = 255; |
|||
st[i].y = 255; |
|||
cn->ready = 1; |
|||
} |
|||
} |
|||
|
|||
//GUARDS
|
|||
if ((tmp = getGuardPixel(guards, shot->x, shot->y))) |
|||
{ |
|||
--tmp; |
|||
setGuardPixel(guards, shot->x, shot->y, tmp); |
|||
cn->ready = 1; |
|||
goto invader_shots; |
|||
} |
|||
|
|||
//INVADER
|
|||
if ((tmp = getInvaderPixel(iv, shot->x, shot->y))) |
|||
{ |
|||
--tmp; |
|||
setInvaderPixel(iv, shot->x, shot->y, tmp); |
|||
|
|||
if (tmp == 0) |
|||
{ |
|||
iv->speedinc++; |
|||
if (iv->speedinc == SPEED_INC_RATE) |
|||
{ |
|||
iv->speedinc = 0; |
|||
iv->speed -= SPEED_INC_VALUE; |
|||
} |
|||
pl->points += POINTS_FOR_KILL; |
|||
} |
|||
else |
|||
{ |
|||
pl->points += POINTS_FOR_HIT; |
|||
} |
|||
cn->ready = 1; |
|||
goto invader_shots; |
|||
} |
|||
|
|||
//SPACESHIP
|
|||
|
|||
if (shot->y == SPACESHIP_LINE) |
|||
{ |
|||
if (shot->x == sc->pos || shot->x == sc->pos + 1) |
|||
{ |
|||
sc->pos = 255; |
|||
pl->points += POINTS_FOR_SPACESHIP; |
|||
cn->ready = 1; |
|||
goto invader_shots; |
|||
} |
|||
} |
|||
} // !(cn->ready)
|
|||
|
|||
|
|||
invader_shots: for (i = 0; i < MAX_SHOTS; ++i) |
|||
{ |
|||
if ((tmp = getGuardPixel(guards, st[i].x, st[i].y))) |
|||
{ |
|||
--tmp; |
|||
setGuardPixel(guards, st[i].x, st[i].y, tmp); |
|||
st[i].x = 255; |
|||
st[i].y = 255; |
|||
} |
|||
|
|||
if (st[i].y == BORG_HEIGHT - 1) |
|||
{ |
|||
if (st[i].x == cn->pos) |
|||
{ |
|||
|
|||
pl->lives--; |
|||
st[i].x = 255; |
|||
st[i].y = 255; |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
void procSpaceship(Spaceship * sc) |
|||
{ |
|||
unsigned char rnd1 = random8(); |
|||
unsigned char rnd2 = random8(); |
|||
|
|||
static unsigned char sct = 0; |
|||
|
|||
if (sc->pos > RIGHT_BORDER) |
|||
{ |
|||
|
|||
if (rnd1 == 73) |
|||
{ |
|||
if (rnd2 >= 200) |
|||
{ |
|||
sc->pos = RIGHT_BORDER; |
|||
sct = 0; |
|||
} |
|||
} |
|||
|
|||
} |
|||
else |
|||
{ |
|||
if (sct == SPACESHIP_SPEED) |
|||
{ |
|||
sct = 0; |
|||
if (sc->pos == 0) |
|||
{ |
|||
sc->pos = 255; |
|||
} |
|||
else |
|||
{ |
|||
sc->pos--; |
|||
} |
|||
} |
|||
} |
|||
sct++; |
|||
} |
|||
|
|||
unsigned char getStatus(Invaders * iv) |
|||
{ |
|||
|
|||
//count Invader!
|
|||
unsigned char x, y, inv = 0; |
|||
for (x = 0; x < MAX_INVADER_WIDTH; ++x) |
|||
{ |
|||
for (y = 0; y < MAX_INVADER_HEIGHT; ++y) |
|||
{ |
|||
if (iv->map[x][y] != 0) |
|||
inv++; |
|||
} |
|||
} |
|||
|
|||
//LEVEL BEREINIGT
|
|||
if (inv == 0) |
|||
return 1; |
|||
|
|||
//INVADERS REACHED EARTH
|
|||
for (x = 0; x < BORG_WIDTH; ++x) |
|||
{ |
|||
if (getInvaderPixel(iv, x, GUARD_LINE + 1)) |
|||
return 2; |
|||
} |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,134 @@ |
|||
#include <stdio.h> |
|||
#include "util.h" |
|||
#include "invaders2.h" |
|||
|
|||
//#include <stdio.h>
|
|||
|
|||
#ifndef __AVR__ |
|||
#define wait(_X) myWait(_X) |
|||
#endif |
|||
|
|||
void borg_invaders() |
|||
{ |
|||
// waitForFire = 0;
|
|||
/****************************************************************/ |
|||
/* INITIALIZE */ |
|||
/****************************************************************/ |
|||
|
|||
Invaders iv; |
|||
Cannon cn; |
|||
Player pl; |
|||
Spaceship sc; |
|||
|
|||
unsigned char guards[BORG_WIDTH]; |
|||
|
|||
unsigned char level = 0; |
|||
unsigned char ivStatus = 0; |
|||
|
|||
uPixel st[MAX_SHOTS] = |
|||
{ |
|||
{ 255, 255}, |
|||
{ 255, 255}, |
|||
{ 255, 255}, |
|||
{ 255, 255}, |
|||
{ 255, 255} |
|||
}; |
|||
|
|||
uPixel shot; |
|||
// = {0,0};
|
|||
|
|||
pl.points = 0; |
|||
pl.lives = 3; |
|||
|
|||
//--------Init Cannon-------//
|
|||
//cn.pos = 4;
|
|||
//cn.ready = 1;
|
|||
|
|||
/****************************************************************/ |
|||
/* INTRO */ |
|||
/****************************************************************/ |
|||
//drawIntroScreen(2000);
|
|||
|
|||
|
|||
/****************************************************************/ |
|||
/* GAME LOOP */ |
|||
/****************************************************************/ |
|||
do |
|||
{ |
|||
//----- INITIALIZE LEVEL-----//
|
|||
initGuards(guards); |
|||
initInvaders(&iv, level); |
|||
|
|||
//Spaceship
|
|||
sc.lives = 1; |
|||
sc.pos = 255; |
|||
|
|||
//Cannon
|
|||
cn.pos = 7; |
|||
cn.ready = 1; |
|||
|
|||
draw(&iv, &sc, &pl, &cn, guards, st, &shot); |
|||
|
|||
while (1) |
|||
{ |
|||
procInvaders(&iv, st); |
|||
procSpaceship(&sc); |
|||
|
|||
procShots(&iv, &pl, &cn, &sc, guards, st, &shot); |
|||
procCannon(&cn, &shot); |
|||
|
|||
draw(&iv, &sc, &pl, &cn, guards, st, &shot); |
|||
|
|||
ivStatus = getStatus(&iv); |
|||
|
|||
if (ivStatus == 2) //LOST
|
|||
{ |
|||
//pl.lives--;
|
|||
pl.lives = 0; |
|||
break; |
|||
|
|||
} |
|||
else if (ivStatus == 1) //WON
|
|||
{ |
|||
unsigned int bonus= POINTS_FOR_LEVEL * (level + 1) * (12 - iv.pos.y); |
|||
pl.points += bonus; |
|||
//printf("cleared l: %d , y: %d bonus: %d \n",
|
|||
// level, iv.pos.y, bonus);
|
|||
if (level == MAX_LEVEL - 1) |
|||
{ |
|||
level = 0; |
|||
} |
|||
else |
|||
{ |
|||
level = (level + 1); |
|||
} |
|||
break; |
|||
} |
|||
|
|||
if (pl.lives <= 0) |
|||
{ |
|||
//scrolltext("GAME OVER",0,80);
|
|||
break; |
|||
} |
|||
|
|||
wait (WAIT_MS); |
|||
} //IN LEVEL LOOP
|
|||
|
|||
} while (pl.lives > 0); //GAME LOOP
|
|||
|
|||
clearScreen (); |
|||
//wait(5000);
|
|||
char text[64]; |
|||
snprintf(text, 64, "</#points: %u", pl.points); |
|||
scrolltext(text); |
|||
//printf("scores: %d\n", pl.points);
|
|||
|
|||
|
|||
/****************************************************************/ |
|||
/* PLAYER STAT */ |
|||
/* HIGH SCORES */ |
|||
/****************************************************************/ |
|||
|
|||
// waitForFire = 1;
|
|||
|
|||
} |
@ -0,0 +1,182 @@ |
|||
/* Space INVADERS V0.2
|
|||
* |
|||
* by: Fabian Bremerich |
|||
* Thanx to: Peter F. |
|||
* |
|||
* date: Mi, 08.03.2006 |
|||
* |
|||
*/ |
|||
|
|||
#ifndef INVADERS2_H |
|||
#define INVADERS2_H |
|||
|
|||
#define USE_ORIGINAL_PIXEL_API |
|||
|
|||
/*CONNECTION TO SIMULATOR*/ |
|||
//extern char fkey;
|
|||
|
|||
/* TEST PARTS NEW API */ |
|||
|
|||
typedef struct |
|||
{ |
|||
signed char x; |
|||
signed char y; |
|||
} sPixel; |
|||
|
|||
typedef struct |
|||
{ |
|||
unsigned char x; |
|||
unsigned char y; |
|||
} uPixel; |
|||
|
|||
//for compatibility to pisel.h api!
|
|||
#ifdef USE_ORIGINAL_PIXEL_API |
|||
#include "pixel.h" |
|||
#include "scrolltext.h" |
|||
#include "joystick.h" |
|||
|
|||
//typedef uPixel pixel;
|
|||
#define uPixel pixel |
|||
//#define getPixel(_X, _Y) get_pixel( (pixel){_X, _Y})
|
|||
#define clearScreen() clear_screen(0) |
|||
//#define
|
|||
|
|||
//#ifdef SIMULATOR
|
|||
#define setPixel(_X, _Y, _V) setpixel( (pixel){_X, _Y}, _V) |
|||
//#else //if defined (AVR)
|
|||
//#define setPixel(_X, _Y, _V) reverseSetPixel( (pixel){_X, _Y}, _V)
|
|||
//#endif
|
|||
|
|||
#endif |
|||
|
|||
/****************************************************************/ |
|||
/* GLOBALE VAR */ |
|||
/****************************************************************/ |
|||
#define P 3 |
|||
extern unsigned char peter[8][11]; |
|||
extern unsigned char hans[8][11]; |
|||
|
|||
/****************************************************************/ |
|||
/* DEFINES */ |
|||
/****************************************************************/ |
|||
#define START_LIVES 3 |
|||
|
|||
#define SPACESHIP_LINE 1 |
|||
//#define SPACESHIP_TRIGGER_POINTS 250
|
|||
//#define SPACESHIP_TRIGGER_RATE 333
|
|||
|
|||
|
|||
#define GUARD_LINE 13 |
|||
|
|||
#define BORG_WIDTH 16 |
|||
#define BORG_HEIGHT 16 |
|||
|
|||
#ifdef SWITCHED_SIDE |
|||
#define RIGHT_BORDER 0 |
|||
#define LEFT_BORDER (BORG_WIDTH -1 ) |
|||
#else |
|||
#define RIGHT_BORDER (BORG_WIDTH -1 ) |
|||
#define LEFT_BORDER 0 |
|||
#endif |
|||
|
|||
#define MAX_INVADER_HEIGHT 8 |
|||
#define MAX_INVADER_WIDTH 12 |
|||
#define MAX_INVADER_LIVES 3 |
|||
|
|||
#define POINTS_FOR_HIT 5 |
|||
#define POINTS_FOR_KILL 25 |
|||
#define POINTS_FOR_SPACESHIP 75 |
|||
#define POINTS_FOR_LEVEL 100 |
|||
|
|||
#define MAX_SHOTS 7 |
|||
#define MIN_SPEED 70 |
|||
#define SPEED_INC_RATE 2 |
|||
#define SPEED_INC_VALUE 3 |
|||
#define MAX_LEVEL 5 |
|||
|
|||
#define SHOOTING_RATE 6 |
|||
#define INVADER_SHOOTING_SPEED 10 |
|||
#define CANNON_SHOOTING_SPEED 4 |
|||
#define SPACESHIP_SPEED 30 |
|||
|
|||
#define CANNON_SPEED 2 |
|||
|
|||
#define WAIT_MS 15 |
|||
//#define WAIT_MS 20
|
|||
|
|||
|
|||
typedef struct |
|||
{ |
|||
unsigned char map[MAX_INVADER_WIDTH][MAX_INVADER_HEIGHT]; |
|||
sPixel pos; |
|||
|
|||
unsigned char speed; |
|||
unsigned char speedinc; |
|||
signed char direction; |
|||
unsigned char isEdged; |
|||
} Invaders; |
|||
|
|||
typedef struct |
|||
{ |
|||
unsigned char pos; |
|||
unsigned char lives; |
|||
} Spaceship; |
|||
|
|||
typedef struct |
|||
{ |
|||
unsigned char pos; |
|||
unsigned char ready; |
|||
} Cannon; |
|||
|
|||
//typedef struct {
|
|||
// unsigned char guards[numGards];
|
|||
//}
|
|||
|
|||
typedef struct |
|||
{ |
|||
signed char lives; |
|||
unsigned int points; |
|||
} Player; |
|||
|
|||
/****************************************************************/ |
|||
/* FUNCTIONS */ |
|||
/****************************************************************/ |
|||
|
|||
void borg_invaders(); |
|||
/*----------------------main_level_funcs-------------------------*/ |
|||
|
|||
void procSpaceship(Spaceship * sp); |
|||
void procCannon(Cannon * cn, uPixel * shot); |
|||
|
|||
void procInvaders(Invaders * iv, uPixel st[MAX_SHOTS]); |
|||
void procShots(Invaders * iv, Player * pl, Cannon * cn, Spaceship * sc, |
|||
unsigned char guards[BORG_WIDTH], uPixel st[MAX_SHOTS], uPixel * shot); |
|||
|
|||
unsigned char getStatus(Invaders * iv); |
|||
|
|||
/*----------------------Initialization---------------------------*/ |
|||
void initGuards(unsigned char guards[BORG_WIDTH]); |
|||
void initInvaders(Invaders * iv, unsigned char lv); |
|||
//void initSpaceship(Spaceship* sc);
|
|||
//void initPlayer(Player* pl);
|
|||
|
|||
/*----------------------getter/setter----------------------------*/ |
|||
|
|||
unsigned char getInvaderPixel(Invaders * iv, unsigned char x, unsigned char y); |
|||
|
|||
void setInvaderPixel(Invaders * iv, unsigned char x, unsigned char y, |
|||
unsigned char val); |
|||
|
|||
unsigned char getGuardPixel(unsigned char guards[BORG_WIDTH], unsigned char x, |
|||
unsigned char y); |
|||
|
|||
void setGuardPixel(unsigned char guards[BORG_WIDTH], unsigned char x, |
|||
unsigned char y, unsigned char val); |
|||
|
|||
/*----------------------drawing Method---------------------------*/ |
|||
|
|||
void draw(Invaders * iv, Spaceship * sc, Player * pl, Cannon * cn, |
|||
unsigned char guards[BORG_WIDTH], uPixel ishots[MAX_SHOTS], |
|||
uPixel * shot); |
|||
|
|||
#endif |
@ -0,0 +1,19 @@ |
|||
Copyright (c) 2007 Christian Kroll |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to |
|||
deal in the Software without restriction, including without limitation the |
|||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
|||
sell copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in |
|||
all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
|||
IN THE SOFTWARE. |
@ -0,0 +1,19 @@ |
|||
Copyright (c) 2007 Christian Kroll |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to |
|||
deal in the Software without restriction, including without limitation the |
|||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
|||
sell copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in |
|||
all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
|||
IN THE SOFTWARE. |
@ -0,0 +1,25 @@ |
|||
LD = avr-ld |
|||
|
|||
all: tetris.o |
|||
|
|||
tetris.o: piece.o playfield.o view.o logic.o input.o |
|||
$(LD) -r piece.o playfield.o view.o logic.o input.o -o tetris.o |
|||
|
|||
piece.o: piece.c piece.h |
|||
$(MCU_CC) $(CFLAGS) -c piece.c -o piece.o |
|||
|
|||
playfield.o: playfield.c playfield.h piece.h |
|||
$(MCU_CC) $(CFLAGS) -c playfield.c -o playfield.o |
|||
|
|||
view.o: view.c view.h logic.h piece.h playfield.h ../config.h ../pixel.h \ |
|||
../util.h ../scrolltext.h |
|||
$(MCU_CC) $(CFLAGS) -c view.c -o view.o |
|||
|
|||
logic.o: logic.c logic.h piece.h playfield.h input.h view.h |
|||
$(MCU_CC) $(CFLAGS) -c logic.c -o logic.o |
|||
|
|||
input.o: input.c input.h ../joystick.h ../util.h |
|||
$(MCU_CC) $(CFLAGS) -c input.c -o input.o |
|||
|
|||
clean: |
|||
rm -rf *.o *.d |
@ -0,0 +1,400 @@ |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <inttypes.h> |
|||
#include <assert.h> |
|||
#include "../joystick.h" |
|||
#include "../util.h" |
|||
#include "input.h" |
|||
|
|||
/* - the API simulator and the real API have different named wait functions
|
|||
* - the macro PM helps in reading values from PROGMEM on the AVR arch |
|||
*/ |
|||
#ifdef __AVR__ |
|||
#include <avr/pgmspace.h> |
|||
#define WAIT(ms) wait(ms) |
|||
#define PM(value) pgm_read_word(&value) |
|||
#else |
|||
#define PROGMEM |
|||
#define WAIT(ms) myWait(ms) |
|||
#define PM(value) (value) |
|||
#endif |
|||
|
|||
|
|||
/***********
|
|||
* defines * |
|||
***********/ |
|||
|
|||
// amount of milliseconds that each loop cycle waits
|
|||
#define TETRIS_INPUT_TICKS 5 |
|||
|
|||
// amount of milliseconds the input is ignored after the pause combo has been
|
|||
// pressed, since it is difficult to release all buttons simultaneously
|
|||
#define TETRIS_INPUT_PAUSE_TICKS 100 |
|||
|
|||
// amount of allowed loop cycles while in pause mode so that the game
|
|||
// automatically continues after five minutes
|
|||
#define TETRIS_INPUT_PAUSE_CYCLES 60000 |
|||
|
|||
// minimum of cycles in gliding mode
|
|||
#define TETRIS_INPUT_GLIDE_CYCLES 75 |
|||
|
|||
// here you can adjust the delays (in loop cycles) for key repeat
|
|||
#define TETRIS_INPUT_REPEAT_INITIALDELAY 40 |
|||
#define TETRIS_INPUT_REPEAT_DELAY 10 |
|||
|
|||
// Here you can adjust the amount of loop cycles a command is ignored after
|
|||
// its button has been released (to reduce joystick chatter)
|
|||
#define TETRIS_INPUT_CHATTER_TICKS_ROT_CW 24 |
|||
#define TETRIS_INPUT_CHATTER_TICKS_ROT_CCW 24 |
|||
#define TETRIS_INPUT_CHATTER_TICKS_LEFT 12 |
|||
#define TETRIS_INPUT_CHATTER_TICKS_RIGHT 12 |
|||
#define TETRIS_INPUT_CHATTER_TICKS_DOWN 12 |
|||
#define TETRIS_INPUT_CHATTER_TICKS_DROP 24 |
|||
|
|||
|
|||
/***************************
|
|||
* non-interface functions * |
|||
***************************/ |
|||
|
|||
/* Function: tetris_input_chatterProtect;
|
|||
* Description: sets an ignore counter to a command specific value if it is 0 |
|||
* Argument pIn: pointer to an input object |
|||
* Argument cmd: the command whose counter should be set |
|||
* Return value: void |
|||
*/ |
|||
void tetris_input_chatterProtect (tetris_input_t *pIn, |
|||
tetris_input_command_t cmd) |
|||
{ |
|||
// never exceed the index
|
|||
assert(cmd < TETRIS_INCMD_NONE); |
|||
|
|||
// amount of loop cycles a command is ignored after its button has been
|
|||
// released (every command has its own counter)
|
|||
const static uint8_t nInitialIgnoreValue[TETRIS_INCMD_NONE] PROGMEM = |
|||
{ |
|||
TETRIS_INPUT_CHATTER_TICKS_ROT_CW, |
|||
TETRIS_INPUT_CHATTER_TICKS_ROT_CCW, |
|||
TETRIS_INPUT_CHATTER_TICKS_LEFT, |
|||
TETRIS_INPUT_CHATTER_TICKS_RIGHT, |
|||
TETRIS_INPUT_CHATTER_TICKS_DOWN, |
|||
TETRIS_INPUT_CHATTER_TICKS_DROP, |
|||
0, // TETRIS_INCMD_GRAVITY (irrelevant because it doesn't have a button)
|
|||
0 // TETRIS_INCMD_PAUSE (is a combination of ROT_CW and DOWN)
|
|||
}; |
|||
|
|||
// setting ignore counter according to the predefined array
|
|||
if (pIn->nIgnoreCmdCounter[cmd] == 0) |
|||
{ |
|||
// if the command isn't TETRIS_INCMD_PAUSE, setting the ignore counter
|
|||
// is straight forward
|
|||
if (cmd != TETRIS_INCMD_PAUSE) |
|||
{ |
|||
pIn->nIgnoreCmdCounter[cmd] = PM(nInitialIgnoreValue[cmd]); |
|||
} |
|||
// TETRIS_INCMD_PAUSE is issued via a combination of the buttons for
|
|||
// TETRIS_INCMD_ROT_CW and TETRIS_INCMD_DOWN, so we must set their
|
|||
// ignore counters
|
|||
else |
|||
{ |
|||
pIn->nIgnoreCmdCounter[TETRIS_INCMD_ROT_CW] = |
|||
TETRIS_INPUT_CHATTER_TICKS_ROT_CW; |
|||
pIn->nIgnoreCmdCounter[TETRIS_INCMD_DOWN] = |
|||
TETRIS_INPUT_CHATTER_TICKS_DOWN; |
|||
} |
|||
} |
|||
|
|||
// The ignore counter of TETRIS_INCMD_PAUSE is either set to the counter
|
|||
// value of TETRIS_INCMD_ROT_CW or TETRIS_INCMD_DOWN (whichever is higher).
|
|||
if ((cmd == TETRIS_INCMD_ROT_CW) || (cmd == TETRIS_INCMD_DOWN)) |
|||
{ |
|||
// helper variables (which the compiler hopefully optimizes away)
|
|||
uint8_t nRotCw = pIn->nIgnoreCmdCounter[TETRIS_INCMD_ROT_CW]; |
|||
uint8_t nDown = pIn->nIgnoreCmdCounter[TETRIS_INCMD_DOWN]; |
|||
|
|||
pIn->nIgnoreCmdCounter[TETRIS_INCMD_PAUSE] = |
|||
(nRotCw > nDown ? nRotCw : nDown); |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_input_queryJoystick
|
|||
* Description: translates joystick movements into tetris_input_command_t |
|||
* Argument pIn: pointer to an input object |
|||
* Return value: see definition of tetris_input_command_t |
|||
*/ |
|||
tetris_input_command_t tetris_input_queryJoystick() |
|||
{ |
|||
tetris_input_command_t cmdReturn; |
|||
|
|||
if (JOYISFIRE) |
|||
{ |
|||
cmdReturn = TETRIS_INCMD_DROP; |
|||
} |
|||
else if (JOYISLEFT) |
|||
{ |
|||
cmdReturn = TETRIS_INCMD_LEFT; |
|||
} |
|||
else if (JOYISRIGHT) |
|||
{ |
|||
cmdReturn = TETRIS_INCMD_RIGHT; |
|||
} |
|||
else if (JOYISUP && JOYISDOWN) |
|||
{ |
|||
cmdReturn = TETRIS_INCMD_PAUSE; |
|||
WAIT(TETRIS_INPUT_PAUSE_TICKS); |
|||
} |
|||
else if (JOYISDOWN) |
|||
{ |
|||
cmdReturn = TETRIS_INCMD_DOWN; |
|||
} |
|||
else if (JOYISUP) |
|||
{ |
|||
cmdReturn = TETRIS_INCMD_ROT_CW; |
|||
} |
|||
else |
|||
{ |
|||
cmdReturn = TETRIS_INCMD_NONE; |
|||
} |
|||
|
|||
return cmdReturn; |
|||
} |
|||
|
|||
|
|||
/*****************************
|
|||
* construction/destruction * |
|||
*****************************/ |
|||
|
|||
/* Function: tetris_input_construct
|
|||
* Description: constructs an input object for André's borg |
|||
* Return value: pointer to a newly created input object |
|||
*/ |
|||
tetris_input_t *tetris_input_construct() |
|||
{ |
|||
tetris_input_t *pIn = (tetris_input_t *)malloc(sizeof(tetris_input_t)); |
|||
assert(pIn != NULL); |
|||
|
|||
pIn->cmdLast = TETRIS_INCMD_NONE; |
|||
pIn->nLevel = 0xFF; |
|||
tetris_input_setLevel(pIn, 0); |
|||
pIn->nLoopCycles = 0; |
|||
pIn->nRepeatCount = -TETRIS_INPUT_REPEAT_INITIALDELAY; |
|||
pIn->nPauseCount = 0; |
|||
memset(pIn->nIgnoreCmdCounter, 0, TETRIS_INCMD_NONE); |
|||
|
|||
return pIn; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_input_destruct
|
|||
* Description: destructs an input structure |
|||
* Argument pIn: pointer to the input object which should to be destructed |
|||
* Return value: void |
|||
*/ |
|||
void tetris_input_destruct(tetris_input_t *pIn) |
|||
{ |
|||
assert(pIn != NULL); |
|||
free(pIn); |
|||
} |
|||
|
|||
|
|||
/***************************
|
|||
* input related functions * |
|||
***************************/ |
|||
|
|||
/* Function: retris_input_getCommand
|
|||
* Description: retrieves commands from joystick or loop interval |
|||
* Argument pIn: pointer to an input object |
|||
* Argument nPace: falling pace (see definition of tetris_input_pace_t) |
|||
* Return value: see definition of tetris_input_command_t |
|||
*/ |
|||
tetris_input_command_t tetris_input_getCommand(tetris_input_t *pIn, |
|||
tetris_input_pace_t nPace) |
|||
{ |
|||
assert (pIn != NULL); |
|||
|
|||
// holds the translated command value of the joystick
|
|||
tetris_input_command_t cmdJoystick = TETRIS_INCMD_NONE; |
|||
|
|||
// this variable both serves as the return value and as a flag for not
|
|||
// leaving the function as long as its value is TETRIS_INCMD_NONE
|
|||
tetris_input_command_t cmdReturn = TETRIS_INCMD_NONE; |
|||
|
|||
uint8_t nMaxCycles; |
|||
|
|||
// if the piece is gliding we grant the player a reasonable amount of time
|
|||
// to make the game more controllable at higher falling speeds
|
|||
if ((nPace == TETRIS_INPACE_GLIDING) && |
|||
(pIn->nMaxCycles < TETRIS_INPUT_GLIDE_CYCLES)) |
|||
{ |
|||
nMaxCycles = TETRIS_INPUT_GLIDE_CYCLES; |
|||
} |
|||
else |
|||
{ |
|||
nMaxCycles = pIn->nMaxCycles; |
|||
} |
|||
|
|||
while (pIn->nLoopCycles < nMaxCycles) |
|||
{ |
|||
cmdJoystick = tetris_input_queryJoystick(); |
|||
|
|||
// only obey current command if it is not considered as chattering
|
|||
if (((cmdJoystick < TETRIS_INCMD_NONE) ? |
|||
pIn->nIgnoreCmdCounter[cmdJoystick] : 0) == 0) |
|||
{ |
|||
switch (cmdJoystick) |
|||
{ |
|||
case TETRIS_INCMD_LEFT: |
|||
case TETRIS_INCMD_RIGHT: |
|||
case TETRIS_INCMD_DOWN: |
|||
// only react if either the current command differs from the
|
|||
// last one or enough loop cycles have been run on the same
|
|||
// command (for key repeat)
|
|||
if ((pIn->cmdLast != cmdJoystick) |
|||
|| ((pIn->cmdLast == cmdJoystick) |
|||
&& (pIn->nRepeatCount >= TETRIS_INPUT_REPEAT_DELAY))) |
|||
{ |
|||
// reset repeat counter
|
|||
if (pIn->cmdLast != cmdJoystick) |
|||
{ |
|||
// different command: we set an extra initial delay
|
|||
pIn->nRepeatCount = -TETRIS_INPUT_REPEAT_INITIALDELAY; |
|||
} |
|||
else |
|||
{ |
|||
// same command: there's no extra initial delay
|
|||
pIn->nRepeatCount = 0; |
|||
} |
|||
|
|||
// update cmdLast and return value
|
|||
pIn->cmdLast = cmdReturn = cmdJoystick; |
|||
} |
|||
else |
|||
{ |
|||
// if not enough loop cycles have been run we increment the
|
|||
// repeat counter, ensure that we continue the loop and
|
|||
// keep the key repeat functioning
|
|||
++pIn->nRepeatCount; |
|||
cmdReturn = TETRIS_INCMD_NONE; |
|||
} |
|||
break; |
|||
|
|||
case TETRIS_INCMD_DROP: |
|||
case TETRIS_INCMD_ROT_CW: |
|||
case TETRIS_INCMD_ROT_CCW: |
|||
// no key repeat here
|
|||
if (pIn->cmdLast != cmdJoystick) |
|||
{ |
|||
pIn->cmdLast = cmdReturn = cmdJoystick; |
|||
} |
|||
else |
|||
{ |
|||
// if we reach here the command is ignored
|
|||
cmdReturn = TETRIS_INCMD_NONE; |
|||
} |
|||
break; |
|||
|
|||
case TETRIS_INCMD_PAUSE: |
|||
// if this is an initial pause command, make sure that the logic
|
|||
// module is informed about it
|
|||
if (pIn->cmdLast != TETRIS_INCMD_PAUSE) |
|||
{ |
|||
pIn->cmdLast = cmdReturn = cmdJoystick; |
|||
pIn->nPauseCount = 0; |
|||
} |
|||
// consecutive pause commands should not cause the loop to leave
|
|||
else |
|||
{ |
|||
cmdReturn = TETRIS_INCMD_NONE; |
|||
} |
|||
break; |
|||
|
|||
case TETRIS_INCMD_NONE: |
|||
// chatter protection
|
|||
if (pIn->cmdLast != TETRIS_INCMD_NONE) |
|||
{ |
|||
tetris_input_chatterProtect(pIn, pIn->cmdLast); |
|||
} |
|||
|
|||
// If the game is paused (last command was TETRIS_INCMD_PAUSE)
|
|||
// we ensure that the variable which holds that last command
|
|||
// isn't touched. We use this as a flag so that the loop cycle
|
|||
// counter doesn't get incremented.
|
|||
// We count the number of pause cycles, though. If enough pause
|
|||
// cycles have been run, we enforce the continuation of the game.
|
|||
if ((pIn->cmdLast != TETRIS_INCMD_PAUSE) || |
|||
(++pIn->nPauseCount > TETRIS_INPUT_PAUSE_CYCLES)) |
|||
{ |
|||
pIn->cmdLast = TETRIS_INCMD_NONE; |
|||
} |
|||
|
|||
// reset repeat counter
|
|||
pIn->nRepeatCount = -TETRIS_INPUT_REPEAT_INITIALDELAY; |
|||
|
|||
// using cmdReturn as a flag for not leaving the loop
|
|||
cmdReturn = TETRIS_INCMD_NONE; |
|||
break; |
|||
|
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
// current command is considered as chattering
|
|||
else |
|||
{ |
|||
pIn->cmdLast = cmdReturn = TETRIS_INCMD_NONE; |
|||
} |
|||
|
|||
// decrement all ignore counters
|
|||
for (int nIgnoreIndex = 0; nIgnoreIndex < TETRIS_INCMD_NONE; ++nIgnoreIndex) |
|||
{ |
|||
if (pIn->nIgnoreCmdCounter[nIgnoreIndex] != 0) |
|||
{ |
|||
--pIn->nIgnoreCmdCounter[nIgnoreIndex]; |
|||
} |
|||
} |
|||
|
|||
// reset automatic falling if the player has dropped a piece
|
|||
if ((cmdReturn == TETRIS_INCMD_DOWN) |
|||
|| (cmdReturn == TETRIS_INCMD_DROP)) |
|||
{ |
|||
pIn->nLoopCycles = 0; |
|||
} |
|||
// otherwise ensure automatic falling (unless the game is running)
|
|||
else if ((cmdReturn != TETRIS_INCMD_PAUSE) && |
|||
!((cmdReturn == TETRIS_INCMD_NONE) && |
|||
(pIn->cmdLast == TETRIS_INCMD_PAUSE))) |
|||
{ |
|||
++pIn->nLoopCycles; |
|||
} |
|||
|
|||
WAIT(TETRIS_INPUT_TICKS); |
|||
if (cmdReturn != TETRIS_INCMD_NONE) |
|||
{ |
|||
return cmdReturn; |
|||
} |
|||
} |
|||
|
|||
// since we have left the loop we reset the cycle counter
|
|||
pIn->nLoopCycles = 0; |
|||
|
|||
return TETRIS_INCMD_GRAVITY; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_input_setLevel
|
|||
* Description: modifies time interval of input events |
|||
* Argument pIn: pointer to an input object |
|||
* Argument nLvl: desired level (0 <= nLvl <= TETRIS_INPUT_LEVELS - 1) |
|||
* Return value: void |
|||
*/ |
|||
void tetris_input_setLevel(tetris_input_t *pIn, |
|||
uint8_t nLvl) |
|||
{ |
|||
assert(pIn != NULL); |
|||
assert(nLvl <= TETRIS_INPUT_LEVELS - 1); |
|||
if (pIn->nLevel != nLvl) |
|||
{ |
|||
pIn->nLevel = nLvl; |
|||
pIn->nMaxCycles = 400 / (nLvl + 2); |
|||
} |
|||
} |
@ -0,0 +1,129 @@ |
|||
#ifndef INPUT_H_ |
|||
#define INPUT_H_ |
|||
|
|||
#include <inttypes.h> |
|||
|
|||
|
|||
/***********
|
|||
* defines * |
|||
***********/ |
|||
|
|||
// number of levels
|
|||
#define TETRIS_INPUT_LEVELS 20 |
|||
|
|||
|
|||
/*********
|
|||
* types * |
|||
*********/ |
|||
|
|||
typedef enum tetris_input_command_t |
|||
{ |
|||
TETRIS_INCMD_ROT_CW, // rotate clockwise
|
|||
TETRIS_INCMD_ROT_CCW, // rotate counter clockwise
|
|||
TETRIS_INCMD_LEFT, // move piece left
|
|||
TETRIS_INCMD_RIGHT, // move piece right
|
|||
TETRIS_INCMD_DOWN, // lower piece by one row
|
|||
TETRIS_INCMD_DROP, // move piece to the ground immediately
|
|||
TETRIS_INCMD_GRAVITY, // piece gets pulled by gravity
|
|||
TETRIS_INCMD_PAUSE, // pause the game
|
|||
TETRIS_INCMD_NONE // idle (must alway be the last one)
|
|||
} |
|||
tetris_input_command_t; |
|||
|
|||
|
|||
typedef enum tetris_input_pace_t |
|||
{ |
|||
TETRIS_INPACE_HOVERING, // normal falling pace
|
|||
TETRIS_INPACE_GLIDING /* guarantees a minimum docking time to avoid that
|
|||
pieces are docked immediately if they hit something |
|||
in higher levels */ |
|||
} |
|||
tetris_input_pace_t; |
|||
|
|||
|
|||
typedef struct tetris_input_t |
|||
{ |
|||
// current level (determines falling speed)
|
|||
uint8_t nLevel; |
|||
|
|||
// Amount of loop cycles between forced piece movements. This value gets
|
|||
// set via the tetris_input_setLevel() function.
|
|||
uint8_t nMaxCycles; |
|||
|
|||
// This counter keeps track of the number of loop cycles whoch have been
|
|||
// done since the last forced piece movement. It gets reset if it either
|
|||
// reaches a well defined value (causing a gravity command to be issued)
|
|||
// or the player has moved down the piece herself/himself.
|
|||
uint8_t nLoopCycles; |
|||
|
|||
// Amount of loop cycles in which the same command has been issued
|
|||
// consecutively. It gets reset if either the current command differs from
|
|||
// the last one or a well-defined value has been reached (thereby
|
|||
// regulating the pace of the key repeat as commands are only processed
|
|||
// if that value is reached).
|
|||
int8_t nRepeatCount; |
|||
|
|||
// Keeps track of the number loop cycles which have been run while in
|
|||
// pause mode. As soon as a well defined value is reached, the game
|
|||
// continues (in case someone paused the game and forgot to resume it).
|
|||
uint16_t nPauseCount; |
|||
|
|||
|
|||
// last command (important for key repeat)
|
|||
tetris_input_command_t cmdLast; |
|||
|
|||
// Every command has its own counter. A command is ignored as long as its
|
|||
// counter is unequal to 0. A counter gets set to a specific value (or 0)
|
|||
// if the button of the corresponding command has been released by the
|
|||
// player. All counters get decremented by one every loop cycle until they
|
|||
// are zero. This is used to work against joystick chatter. Look at the
|
|||
// TETRIS_INPUT_CHATTER_TICKS_... constants in input.c for the initial
|
|||
// values of these counters.
|
|||
uint8_t nIgnoreCmdCounter[TETRIS_INCMD_NONE]; |
|||
} |
|||
tetris_input_t; |
|||
|
|||
/****************************
|
|||
* construction/destruction * |
|||
****************************/ |
|||
|
|||
/* Function: tetris_input_construct
|
|||
* Description: constructs an input object for André's borg |
|||
* Return value: pointer to a newly created input object |
|||
*/ |
|||
tetris_input_t *tetris_input_construct(); |
|||
|
|||
|
|||
/* Function: tetris_input_destruct
|
|||
* Description: destructs an input object |
|||
* Argument pIn: pointer to the input object which should be destructed |
|||
* Return value: void |
|||
*/ |
|||
void tetris_input_destruct(tetris_input_t *pIn); |
|||
|
|||
|
|||
/***************************
|
|||
* input related functions * |
|||
***************************/ |
|||
|
|||
/* Function: retris_input_getCommand
|
|||
* Description: retrieves commands from joystick or loop interval |
|||
* Argument pIn: pointer to an input object |
|||
* Argument nPace: falling pace (see definition of tetris_input_pace_t) |
|||
* Return value: see definition of tetris_input_command_t |
|||
*/ |
|||
tetris_input_command_t tetris_input_getCommand(tetris_input_t *pIn, |
|||
tetris_input_pace_t nPace); |
|||
|
|||
|
|||
/* Function: tetris_input_setLevel
|
|||
* Description: modifies time interval of input events |
|||
* Argument pIn: pointer to an input object |
|||
* Argument nLvl: desired level (0 <= nLvl <= TETRIS_INPUT_LEVELS - 1) |
|||
* Return value: void |
|||
*/ |
|||
void tetris_input_setLevel(tetris_input_t *pIn, |
|||
uint8_t nLvl); |
|||
|
|||
|
|||
#endif /*INPUT_H_*/ |
@ -0,0 +1,467 @@ |
|||
/* Borgtris
|
|||
* by: Christian Kroll |
|||
* date: Tuesday, 2007/09/16 |
|||
*/ |
|||
|
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <assert.h> |
|||
#include <inttypes.h> |
|||
|
|||
#ifdef __AVR__ |
|||
#include <avr/eeprom.h> |
|||
#include <avr/interrupt.h> |
|||
#endif |
|||
|
|||
#include "logic.h" |
|||
#include "piece.h" |
|||
#include "playfield.h" |
|||
#include "view.h" |
|||
#include "input.h" |
|||
#include "../prng.h" |
|||
|
|||
|
|||
#ifdef EEMEM |
|||
/***********************
|
|||
* Highscore in EEPROM * |
|||
***********************/ |
|||
|
|||
uint16_t tetris_logic_nHighscore EEMEM; |
|||
#endif |
|||
|
|||
/***************************
|
|||
* non-interface functions * |
|||
***************************/ |
|||
|
|||
/* Function: tetris_logic_calculateLines
|
|||
* Description: calculates number of lines for the given row mask |
|||
* Argument nRowMask: row mask from which the no. of lines will be calculated |
|||
* Return value: number of lines of the row mask |
|||
*/ |
|||
uint8_t tetris_logic_calculateLines(uint8_t nRowMask) |
|||
{ |
|||
uint8_t nMask = 0x0001; |
|||
uint8_t nLines = 0; |
|||
for (uint8_t i = 0; i < 4; ++i) |
|||
{ |
|||
if ((nMask & nRowMask) != 0) |
|||
{ |
|||
++nLines; |
|||
} |
|||
nMask <<= 1; |
|||
} |
|||
|
|||
return nLines; |
|||
} |
|||
|
|||
uint16_t tetris_logic_retrieveHighscore(void) |
|||
{ |
|||
#ifdef EEMEM |
|||
uint16_t nHighscore = 0; |
|||
nHighscore = eeprom_read_word(&tetris_logic_nHighscore); |
|||
|
|||
// a score of 65535 is most likely caused by uninitialized EEPROM addresses
|
|||
if (nHighscore == 65535) |
|||
{ |
|||
nHighscore = 0; |
|||
} |
|||
|
|||
return nHighscore; |
|||
#else |
|||
return 0; |
|||
#endif |
|||
} |
|||
|
|||
void tetris_logic_saveHighscore(uint16_t nHighscore) |
|||
{ |
|||
#ifdef EEMEM |
|||
if (nHighscore > tetris_logic_retrieveHighscore()) |
|||
{ |
|||
eeprom_write_word(&tetris_logic_nHighscore, nHighscore); |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
/****************************
|
|||
* construction/destruction * |
|||
****************************/ |
|||
|
|||
/* Function: tetris_logic_construct
|
|||
* Description: constructs a logic object |
|||
* Return value: pointer to a newly created logic object |
|||
*/ |
|||
tetris_logic_t *tetris_logic_construct() |
|||
{ |
|||
tetris_logic_t *pLogic = (tetris_logic_t *)malloc(sizeof(tetris_logic_t)); |
|||
assert(pLogic != NULL); |
|||
memset(pLogic, 0, sizeof(tetris_logic_t)); |
|||
return pLogic; |
|||
} |
|||
|
|||
/* Function: tetris_logic_destruct
|
|||
* Description: destructs a logic object |
|||
* Argument pIn: pointer to the logic object to be destructed |
|||
* Return value: void |
|||
*/ |
|||
void tetris_logic_destruct(tetris_logic_t *pLogic) |
|||
{ |
|||
assert(pLogic != 0); |
|||
free(pLogic); |
|||
} |
|||
|
|||
|
|||
/***************************
|
|||
* logic related functions * |
|||
***************************/ |
|||
|
|||
/* Function: tetris
|
|||
* Description: runs the tetris game |
|||
* Return value: void |
|||
*/ |
|||
void tetris () |
|||
{ |
|||
// get view dependent dimensions of the playfield
|
|||
int8_t nWidth; |
|||
int8_t nHeight; |
|||
tetris_view_getDimensions(&nWidth, &nHeight); |
|||
|
|||
// holds the current user command which should be processed
|
|||
tetris_input_command_t inCmd; |
|||
|
|||
// prepare data structures that drive the game...
|
|||
tetris_logic_t *pLogic = tetris_logic_construct(); |
|||
tetris_playfield_t *pPl = tetris_playfield_construct(nWidth, nHeight); |
|||
tetris_input_t *pIn = tetris_input_construct(); |
|||
tetris_view_t *pView = tetris_view_construct(pLogic, pPl); |
|||
|
|||
// runtime variable
|
|||
int8_t nPieceRow; |
|||
|
|||
// retrieve highscore
|
|||
static uint16_t nHighscore = 0; |
|||
if (nHighscore == 0) |
|||
{ |
|||
nHighscore = tetris_logic_retrieveHighscore(); |
|||
} |
|||
|
|||
// initialize current and next piece
|
|||
tetris_piece_t *pPiece = NULL; |
|||
tetris_piece_t *pNextPiece = pPiece = |
|||
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0); |
|||
|
|||
// the view only monitors the logic and the playfield object for the game
|
|||
// status so we must put information like the next piece or the current
|
|||
// highscore to a place where the view can find it
|
|||
tetris_logic_setHighscore(pLogic, nHighscore); |
|||
tetris_logic_setPreviewPiece(pLogic, pNextPiece); |
|||
|
|||
// pace flag
|
|||
tetris_input_pace_t inPace; |
|||
|
|||
// game loop, runs as long as the game is not over
|
|||
while (tetris_playfield_getStatus(pPl) != TETRIS_PFS_GAMEOVER) |
|||
{ |
|||
// what we do strongly depends on the status of the playfield
|
|||
switch (tetris_playfield_getStatus(pPl)) |
|||
{ |
|||
// the playfield awaits a new piece
|
|||
case TETRIS_PFS_READY: |
|||
// make preview piece the current piece and create new preview piece
|
|||
pPiece = pNextPiece; |
|||
pNextPiece = |
|||
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0); |
|||
tetris_logic_setPreviewPiece(pLogic, pNextPiece); |
|||
|
|||
// insert new piece into playfield
|
|||
tetris_piece_t *pOldPiece; |
|||
tetris_playfield_insertPiece(pPl, pPiece, &pOldPiece); |
|||
|
|||
// destruct old piece (if it exists) since we don't need it anymore
|
|||
if (pOldPiece != NULL) |
|||
{ |
|||
tetris_piece_destruct(pOldPiece); |
|||
pOldPiece = NULL; |
|||
} |
|||
break; |
|||
|
|||
// a piece is hovering and can be controlled by the player
|
|||
case TETRIS_PFS_HOVERING: |
|||
case TETRIS_PFS_GLIDING: |
|||
// if the piece is gliding the input module has to grant us
|
|||
// a minimum amount of time to move it
|
|||
if (tetris_playfield_getStatus(pPl) == TETRIS_PFS_GLIDING) |
|||
{ |
|||
inPace = TETRIS_INPACE_GLIDING; |
|||
} |
|||
else |
|||
{ |
|||
inPace = TETRIS_INPACE_HOVERING; |
|||
} |
|||
|
|||
// ensure correct view mode if the game isn't paused
|
|||
if ((inCmd = tetris_input_getCommand(pIn, inPace)) |
|||
!= TETRIS_INCMD_PAUSE) |
|||
{ |
|||
tetris_view_setViewMode(pView, TETRIS_VIMO_RUNNING); |
|||
} |
|||
|
|||
// what we do depends on what the input module tells us
|
|||
switch (inCmd) |
|||
{ |
|||
// game paused?
|
|||
case TETRIS_INCMD_PAUSE: |
|||
// tell the view it should display the pause screen
|
|||
tetris_view_setViewMode(pView, TETRIS_VIMO_PAUSED); |
|||
break; |
|||
|
|||
// the piece was pulled down by the almighty gravity
|
|||
case TETRIS_INCMD_GRAVITY: |
|||
tetris_playfield_advancePiece(pPl); |
|||
break; |
|||
|
|||
// the player has pulled down the piece herself/himself
|
|||
case TETRIS_INCMD_DOWN: |
|||
tetris_playfield_advancePiece(pPl); |
|||
// if the game still runs, reward the player with extra points
|
|||
if (tetris_playfield_getStatus(pPl) != TETRIS_PFS_GAMEOVER) |
|||
{ |
|||
tetris_logic_singleDrop(pLogic, 1); |
|||
} |
|||
break; |
|||
|
|||
// player shifted the piece to the left
|
|||
case TETRIS_INCMD_LEFT: |
|||
tetris_playfield_movePiece(pPl, TETRIS_PFD_LEFT); |
|||
break; |
|||
|
|||
// player shifted the piece to the right
|
|||
case TETRIS_INCMD_RIGHT: |
|||
tetris_playfield_movePiece(pPl, TETRIS_PFD_RIGHT); |
|||
break; |
|||
|
|||
// player rotated the piece clockwise
|
|||
case TETRIS_INCMD_ROT_CW: |
|||
tetris_playfield_rotatePiece(pPl, TETRIS_PC_ROT_CW); |
|||
break; |
|||
|
|||
// player rotated the piece counter clockwise
|
|||
case TETRIS_INCMD_ROT_CCW: |
|||
tetris_playfield_rotatePiece(pPl, TETRIS_PC_ROT_CCW); |
|||
break; |
|||
|
|||
// the player decided to make an immediate drop
|
|||
case TETRIS_INCMD_DROP: |
|||
nPieceRow = tetris_playfield_getRow(pPl); |
|||
// emulate immediate drop
|
|||
while((tetris_playfield_getStatus(pPl) == TETRIS_PFS_GLIDING) || |
|||
(tetris_playfield_getStatus(pPl) == TETRIS_PFS_HOVERING)) |
|||
{ |
|||
tetris_playfield_advancePiece(pPl); |
|||
} |
|||
// if the game still runs, reward the player with extra points
|
|||
if (tetris_playfield_getStatus(pPl) != TETRIS_PFS_GAMEOVER) |
|||
{ |
|||
tetris_logic_completeDrop(pLogic, |
|||
tetris_playfield_getRow(pPl) - nPieceRow); |
|||
} |
|||
break; |
|||
|
|||
// avoid compiler warnings
|
|||
default: |
|||
break; |
|||
} |
|||
break; |
|||
|
|||
// the piece has irrevocably hit the ground
|
|||
case TETRIS_PFS_DOCKED: |
|||
// remove complete lines (if any)
|
|||
tetris_playfield_removeCompleteLines(pPl); |
|||
|
|||
// let the logic object decide how many points the player gets
|
|||
// and whether the level gets changed
|
|||
tetris_logic_removedLines(pLogic, tetris_playfield_getRowMask(pPl)); |
|||
tetris_input_setLevel(pIn, tetris_logic_getLevel(pLogic)); |
|||
break; |
|||
|
|||
// avoid compiler warnings
|
|||
default: |
|||
break; |
|||
} |
|||
|
|||
// the view updates it state every loop cycle to make changes visible
|
|||
tetris_view_update(pView); |
|||
} |
|||
|
|||
// game is over and we provide the player with her/his results
|
|||
tetris_view_showResults(pView); |
|||
|
|||
// update highscore if it has been beaten
|
|||
uint16_t nScore = tetris_logic_getScore(pLogic); |
|||
if (nScore > nHighscore) |
|||
{ |
|||
nHighscore = nScore; |
|||
tetris_logic_saveHighscore(nHighscore); |
|||
} |
|||
|
|||
// clean up
|
|||
tetris_view_destruct(pView); |
|||
tetris_input_destruct(pIn); |
|||
tetris_playfield_destruct(pPl); |
|||
tetris_logic_destruct(pLogic); |
|||
tetris_piece_destruct(pPiece); |
|||
tetris_piece_destruct(pNextPiece); |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_logic_singleDrop
|
|||
* Description: add points which result from single step dropping |
|||
* Argument pLogic: the logic object we want to modify |
|||
* Argument nLines: the number of rows involved |
|||
* Return value: void |
|||
*/ |
|||
void tetris_logic_singleDrop(tetris_logic_t *pLogic, |
|||
uint8_t nLines) |
|||
{ |
|||
assert(pLogic != 0); |
|||
pLogic->nScore += nLines; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_logic_completeDrop
|
|||
* Description: add points which result from a complete drop |
|||
* Argument pLogic: the logic object we want to modify |
|||
* Argument nLines: the number of rows involved |
|||
* Return value: void |
|||
*/ |
|||
void tetris_logic_completeDrop(tetris_logic_t *pLogic, |
|||
uint8_t nLines) |
|||
{ |
|||
assert(pLogic != 0); |
|||
pLogic->nScore += nLines * 2; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_logic_removedLines
|
|||
* Description: add points which result from removed rows |
|||
* Argument pLogic: the logic object we want to modify |
|||
* Argument nRowMask: see tetris_playfield_completeLines |
|||
* Return value: void |
|||
*/ |
|||
void tetris_logic_removedLines(tetris_logic_t *pLogic, |
|||
uint8_t nRowMask) |
|||
{ |
|||
assert(pLogic != 0); |
|||
uint8_t nLines = tetris_logic_calculateLines(nRowMask); |
|||
pLogic->nLines += nLines; |
|||
pLogic->nLevel = ((pLogic->nLines / 10) < TETRIS_INPUT_LEVELS) ? |
|||
(pLogic->nLines / 10) : (TETRIS_INPUT_LEVELS - 1); |
|||
|
|||
switch (nLines) |
|||
{ |
|||
case 1: |
|||
pLogic->nScore += 50; |
|||
break; |
|||
case 2: |
|||
pLogic->nScore += 150; |
|||
break; |
|||
case 3: |
|||
pLogic->nScore += 250; |
|||
break; |
|||
case 4: |
|||
pLogic->nScore += 400; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
|
|||
/*****************
|
|||
* get functions * |
|||
*****************/ |
|||
|
|||
/* Function: tetris_logic_getScore
|
|||
* Description: returns the current score |
|||
* Argument pLogic: the logic object we want information from |
|||
* Return value: the score as uint16_t |
|||
*/ |
|||
uint16_t tetris_logic_getScore(tetris_logic_t *pLogic) |
|||
{ |
|||
assert(pLogic != NULL); |
|||
return pLogic->nScore; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_logic_getHighscore
|
|||
* Description: returns the current highscore |
|||
* Argument pLogic: the logic object we want information from |
|||
* Return value: the highscore as uint16_t |
|||
*/ |
|||
|
|||
uint16_t tetris_logic_getHighscore(tetris_logic_t *pLogic) |
|||
{ |
|||
assert(pLogic != NULL); |
|||
return pLogic->nHighscore; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_logic_setHighscore
|
|||
* Description: set highscore |
|||
* Argument pLogic: the logic object we want to modify |
|||
* Argmument nHighscore: highscore |
|||
*/ |
|||
void tetris_logic_setHighscore(tetris_logic_t *pLogic, |
|||
uint16_t nHighscore) |
|||
{ |
|||
assert(pLogic != NULL); |
|||
pLogic->nHighscore = nHighscore; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_logic_getLevel
|
|||
* Description: returns the current level |
|||
* Argument pLogic: the logic object we want information from |
|||
* Return value: the level as uint8_t |
|||
*/ |
|||
uint8_t tetris_logic_getLevel(tetris_logic_t *pLogic) |
|||
{ |
|||
assert(pLogic != NULL); |
|||
return pLogic->nLevel; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_logic_getLines
|
|||
* Description: returns the number of completed lines |
|||
* Argument pLogic: the logic object we want information from |
|||
* Return value: number of completed lines as uint16_t |
|||
*/ |
|||
uint16_t tetris_logic_getLines(tetris_logic_t *pLogic) |
|||
{ |
|||
assert(pLogic != NULL); |
|||
return pLogic->nLines; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_logic_setPreviewPiece
|
|||
* Description: help for the view to determine the preview piece |
|||
* Argument pLogic: the logic object we want to modify |
|||
* Argument pPiece: pointer to piece intended to be the next one (may be NULL) |
|||
* Return value: void |
|||
*/ |
|||
void tetris_logic_setPreviewPiece(tetris_logic_t *pLogic, |
|||
tetris_piece_t *pPiece) |
|||
{ |
|||
assert(pLogic != NULL); |
|||
pLogic->pPreviewPiece = pPiece; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_logic_getPreviewPiece
|
|||
* Description: returns piece which was set via tetris_logic_setPreviewPiece |
|||
* Argument pLogic: the logic object we want information from |
|||
* Return value: the piece intended to be the next one (may be NULL) |
|||
*/ |
|||
tetris_piece_t* tetris_logic_getPreviewPiece(tetris_logic_t *pLogic) |
|||
{ |
|||
assert(pLogic != NULL); |
|||
return pLogic->pPreviewPiece; |
|||
} |
|||
|
@ -0,0 +1,143 @@ |
|||
#ifndef TETRIS_LOGIC_H_ |
|||
#define TETRIS_LOGIC_H_ |
|||
|
|||
#include <inttypes.h> |
|||
#include "piece.h" |
|||
|
|||
/*********
|
|||
* types * |
|||
*********/ |
|||
|
|||
typedef struct tetris_logic_t |
|||
{ |
|||
uint16_t nScore; // score of the player
|
|||
uint16_t nHighscore; // highscore
|
|||
uint8_t nLevel; // current level
|
|||
uint16_t nLines; // number of completed lines
|
|||
tetris_piece_t *pPreviewPiece; // the piece intended to be the next one
|
|||
} |
|||
tetris_logic_t; |
|||
|
|||
/****************************
|
|||
* construction/destruction * |
|||
****************************/ |
|||
|
|||
/* Function: tetris_logic_construct
|
|||
* Description: constructs a logic object |
|||
* Return value: pointer to a newly created logic object |
|||
*/ |
|||
tetris_logic_t *tetris_logic_construct(); |
|||
|
|||
/* Function: tetris_logic_destruct
|
|||
* Description: destructs a logic object |
|||
* Argument pIn: pointer to the logic object to be destructed |
|||
* Return value: void |
|||
*/ |
|||
void tetris_logic_destruct(tetris_logic_t *pLogic); |
|||
|
|||
/***************************
|
|||
* logic related functions * |
|||
***************************/ |
|||
|
|||
/* Function: tetris
|
|||
* Description: runs the tetris game |
|||
* Return value: void |
|||
*/ |
|||
void tetris(); |
|||
|
|||
|
|||
/* Function: tetris_logic_singleDrop
|
|||
* Description: add points which result from single step dropping |
|||
* Argument pLogic: the logic object we want to modify |
|||
* Argument nLines: the number of rows involved |
|||
* Return value: void |
|||
*/ |
|||
void tetris_logic_singleDrop(tetris_logic_t *pLogic, |
|||
uint8_t nLines); |
|||
|
|||
|
|||
/* Function: tetris_logic_completeDrop
|
|||
* Description: add points which result from a complete drop |
|||
* Argument pLogic: the logic object we want to modify |
|||
* Argument nLines: the number of rows involved |
|||
* Return value: void |
|||
*/ |
|||
void tetris_logic_completeDrop(tetris_logic_t *pLogic, |
|||
uint8_t nLines); |
|||
|
|||
|
|||
/* Function: tetris_logic_removedLines
|
|||
* Description: add points which result from removed rows |
|||
* Argument pLogic: the logic object we want to modify |
|||
* Argument nRowMask: see tetris_playfield_completeLines |
|||
* Return value: void |
|||
*/ |
|||
void tetris_logic_removedLines(tetris_logic_t *pLogic, |
|||
uint8_t nRowMask); |
|||
|
|||
|
|||
/*********************
|
|||
* get/set functions * |
|||
*********************/ |
|||
|
|||
/* Function: tetris_logic_getScore
|
|||
* Description: returns the current score |
|||
* Argument pLogic: the logic object we want information from |
|||
* Return value: the score as uint16_t |
|||
*/ |
|||
uint16_t tetris_logic_getScore(tetris_logic_t *pLogic); |
|||
|
|||
|
|||
/* Function: tetris_logic_getHighscore
|
|||
* Description: returns the current highscore |
|||
* Argument pLogic: the logic object we want information from |
|||
* Return value: the highscore as uint16_t |
|||
*/ |
|||
uint16_t tetris_logic_getHighscore(tetris_logic_t *pLogic); |
|||
|
|||
|
|||
/* Function: tetris_logic_setHighscore
|
|||
* Description: set highscore |
|||
* Argument pLogic: the logic object we want to modify |
|||
* Argmument nHighscore: highscore |
|||
*/ |
|||
void tetris_logic_setHighscore(tetris_logic_t *pLogic, |
|||
uint16_t nHighscore); |
|||
|
|||
|
|||
/* Function: tetris_logic_getLevel
|
|||
* Description: returns the current level |
|||
* Argument pLogic: the logic object we want information from |
|||
* Return value: the level as uint8_t |
|||
*/ |
|||
uint8_t tetris_logic_getLevel(tetris_logic_t *pLogic); |
|||
|
|||
|
|||
/* Function: tetris_logic_getLines
|
|||
* Description: returns the number of completed lines |
|||
* Argument pLogic: the logic object we want information from |
|||
* Return value: number of completed lines as uint16_t |
|||
*/ |
|||
uint16_t tetris_logic_getLines(tetris_logic_t *pLogic); |
|||
|
|||
|
|||
/* Function: tetris_logic_setPreviewPiece
|
|||
* Description: help for the view to determine the preview piece |
|||
* Argument pLogic: the logic object we want to modify |
|||
* Argument pPiece: pointer to piece intended to be the next one |
|||
* Return value: void |
|||
*/ |
|||
void tetris_logic_setPreviewPiece(tetris_logic_t *pLogic, |
|||
tetris_piece_t *pPiece); |
|||
|
|||
|
|||
/* Function: tetris_logic_getPreviewPiece
|
|||
* Description: returns piece which was set via tetris_logic_setPreviewPiece |
|||
* Argument pLogic: the logic object we want information from |
|||
* Return value: the piece intended to be the next one |
|||
*/ |
|||
tetris_piece_t* tetris_logic_getPreviewPiece(tetris_logic_t *pLogic); |
|||
|
|||
|
|||
#endif /*TETRIS_LOGIC_H_*/ |
|||
|
@ -0,0 +1,119 @@ |
|||
#include <stdlib.h> |
|||
#include <assert.h> |
|||
#include <inttypes.h> |
|||
#include "piece.h" |
|||
|
|||
#ifdef __AVR__ |
|||
#include <avr/pgmspace.h> |
|||
#else |
|||
#define PROGMEM |
|||
#endif |
|||
|
|||
|
|||
/*****************************
|
|||
* construction/destruction * |
|||
*****************************/ |
|||
|
|||
/* Function: tetris_piece_construct
|
|||
* Description: constructs a piece with the given attributes |
|||
* Argument s: shape of the piece (see tetris_piece_shape_t) |
|||
* Argument a: its angle (see tetris_piece_angel_t) |
|||
* Return value: pointer to a newly created piece |
|||
*/ |
|||
tetris_piece_t *tetris_piece_construct(tetris_piece_shape_t s, |
|||
tetris_piece_angle_t a) |
|||
{ |
|||
tetris_piece_t *p_piece = (tetris_piece_t*) malloc (sizeof(tetris_piece_t)); |
|||
assert(p_piece != NULL); |
|||
|
|||
p_piece->shape = s; |
|||
p_piece->angle = a; |
|||
|
|||
return p_piece; |
|||
} |
|||
|
|||
/* Function: tetris_piece_destruct
|
|||
* Description: destructs a piece |
|||
* Argument pPc: pointer to the piece to be destructed |
|||
* Return value: void |
|||
*/ |
|||
void tetris_piece_destruct(tetris_piece_t *pPc) |
|||
{ |
|||
assert(pPc != NULL); |
|||
free(pPc); |
|||
} |
|||
|
|||
|
|||
/****************************
|
|||
* piece related functions * |
|||
****************************/ |
|||
|
|||
/* Function: tetris_piece_getBitmap
|
|||
* Description: returns bitfield representation of the piece |
|||
* Argument pPc: piece from which the bitfield shuld be retrieved |
|||
* Return value: bitfield representation of the piece |
|||
* - nth nibble is nth row of the piece (from upper left) |
|||
* - the LSB of a nibble represents the left side of a row |
|||
*/ |
|||
uint16_t tetris_piece_getBitmap(tetris_piece_t *pPc) |
|||
{ |
|||
assert(pPc != NULL); |
|||
|
|||
// Lookup table:
|
|||
// A value in an array represents a piece in a specific angle (rotating
|
|||
// clockwise from index 0).
|
|||
const static uint16_t piece[][4] PROGMEM = |
|||
{{0x0F00, 0x2222, 0x0F00, 0x2222}, // LINE
|
|||
{0x4E00, 0x4640, 0x0E40, 0x4C40}, // T
|
|||
{0x0660, 0x0660, 0x0660, 0x0660}, // SQUARE
|
|||
{0x2E00, 0x88C0, 0x0E80, 0xC440}, // L
|
|||
{0x8E00, 0x6440, 0x0E20, 0x44C0}, // LBACK
|
|||
{0x6C00, 0x4620, 0x6C00, 0x4620}, // S
|
|||
{0xC600, 0x4C80, 0xC600, 0x4C80}}; // Z
|
|||
|
|||
#ifdef __AVR__ |
|||
return pgm_read_word(&piece[pPc->shape][pPc->angle]); |
|||
#else |
|||
return piece[pPc->shape][pPc->angle]; |
|||
#endif |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_piece_rotate
|
|||
* Description: rotates a piece |
|||
* Argument pPc: piece to rotate |
|||
* Argument r: type of rotation (see tetris_piece_rotation_t) |
|||
* Return value: void |
|||
*/ |
|||
void tetris_piece_rotate(tetris_piece_t *pPc, |
|||
tetris_piece_rotation_t r) |
|||
{ |
|||
assert(pPc != NULL); |
|||
|
|||
// we just rotate through the available angles in the given direction and
|
|||
// make wrap arounds where appropriate
|
|||
switch (r) |
|||
{ |
|||
case TETRIS_PC_ROT_CW: |
|||
if (pPc->angle == TETRIS_PC_ANGLE_270) |
|||
{ |
|||
pPc->angle = TETRIS_PC_ANGLE_0; |
|||
} |
|||
else |
|||
{ |
|||
++pPc->angle; |
|||
} |
|||
break; |
|||
case TETRIS_PC_ROT_CCW: |
|||
if (pPc->angle == TETRIS_PC_ANGLE_0) |
|||
{ |
|||
pPc->angle = TETRIS_PC_ANGLE_270; |
|||
} |
|||
else |
|||
{ |
|||
--pPc->angle; |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
|
@ -0,0 +1,97 @@ |
|||
#ifndef TETRIS_PIECE_H_ |
|||
#define TETRIS_PIECE_H_ |
|||
|
|||
#include <inttypes.h> |
|||
|
|||
|
|||
/*********
|
|||
* types * |
|||
*********/ |
|||
|
|||
typedef enum tetris_piece_shape_t |
|||
{ |
|||
TETRIS_PC_LINE, |
|||
TETRIS_PC_T, |
|||
TETRIS_PC_SQUARE, |
|||
TETRIS_PC_L, |
|||
TETRIS_PC_LBACK, |
|||
TETRIS_PC_S, |
|||
TETRIS_PC_Z |
|||
} |
|||
tetris_piece_shape_t; |
|||
|
|||
|
|||
typedef enum tetris_piece_angle_t |
|||
{ |
|||
TETRIS_PC_ANGLE_0, |
|||
TETRIS_PC_ANGLE_90, |
|||
TETRIS_PC_ANGLE_180, |
|||
TETRIS_PC_ANGLE_270 |
|||
} |
|||
tetris_piece_angle_t; |
|||
|
|||
|
|||
typedef enum tetris_piece_rotation_t |
|||
{ |
|||
TETRIS_PC_ROT_CW, // clockwise rotation
|
|||
TETRIS_PC_ROT_CCW // counter clockwise rotation
|
|||
} |
|||
tetris_piece_rotation_t; |
|||
|
|||
|
|||
typedef struct tetris_piece_t |
|||
{ |
|||
tetris_piece_shape_t shape; // specifies the shape of the piece
|
|||
tetris_piece_angle_t angle; // specifies one of 4 angels
|
|||
} |
|||
tetris_piece_t; |
|||
|
|||
|
|||
/*****************************
|
|||
* construction/destruction * |
|||
*****************************/ |
|||
|
|||
/* Function: tetris_piece_construct
|
|||
* Description: constructs a piece with the given attributes |
|||
* Argument s: shape of the piece (see tetris_piece_shape_t) |
|||
* Argument a: its angle (see tetris_piece_angel_t) |
|||
* Return value: pointer to a newly created piece |
|||
*/ |
|||
tetris_piece_t *tetris_piece_construct(tetris_piece_shape_t s, |
|||
tetris_piece_angle_t a); |
|||
|
|||
|
|||
/* Function: tetris_piece_destruct
|
|||
* Description: destructs a piece |
|||
* Argument pPc: pointer to the piece to be destructed |
|||
* Return value: void |
|||
*/ |
|||
void tetris_piece_destruct(tetris_piece_t *pPc); |
|||
|
|||
|
|||
/****************************
|
|||
* piece related functions * |
|||
****************************/ |
|||
|
|||
/* Function: tetris_piece_getBitmap
|
|||
* Description: returns bitfield representation of the piece |
|||
* Argument pPc: piece from which the bitfield shuld be retrieved |
|||
* Return value: bitfield representation of the piece |
|||
* - nth nibble is nth row of the piece (from upper left) |
|||
* - the LSB of a nibble represents the left side of a row |
|||
*/ |
|||
uint16_t tetris_piece_getBitmap(tetris_piece_t *pPc); |
|||
|
|||
|
|||
/* Function: tetris_piece_rotate
|
|||
* Description: rotates a piece |
|||
* Argument pPc: piece to rotate |
|||
* Argument r: type of rotation (see tetris_piece_rotation_t) |
|||
* Return value: void |
|||
*/ |
|||
void tetris_piece_rotate(tetris_piece_t *pPc, |
|||
tetris_piece_rotation_t r); |
|||
|
|||
|
|||
#endif /*TETRIS_PIECE_H_*/ |
|||
|
@ -0,0 +1,595 @@ |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <assert.h> |
|||
#include <inttypes.h> |
|||
#include "playfield.h" |
|||
#include "piece.h" |
|||
|
|||
|
|||
/***************************
|
|||
* non-interface functions * |
|||
***************************/ |
|||
|
|||
/* Function: tetris_playfield_hoverStatus;
|
|||
* Description: determines if piece is either hovering or gliding |
|||
* Argument pPl: playfield perform action on |
|||
* Return value: TETRIS_PFS_HOVERING or TETRIS_PFS_GLIDING |
|||
*/ |
|||
tetris_playfield_status_t tetris_playfield_hoverStatus(tetris_playfield_t* pPl) |
|||
{ |
|||
// if the piece touches the dump we ensure that the status is "gliding"
|
|||
if (tetris_playfield_collision(pPl, pPl->nColumn, pPl->nRow + 1)) |
|||
{ |
|||
return TETRIS_PFS_GLIDING; |
|||
} |
|||
// otherwise the status must be "hovering"
|
|||
else |
|||
{ |
|||
return TETRIS_PFS_HOVERING; |
|||
} |
|||
} |
|||
|
|||
|
|||
/****************************
|
|||
* construction/destruction * |
|||
****************************/ |
|||
|
|||
/* Function: tetris_playfield_construct
|
|||
* Description: constructs a playfield with the given diemensions |
|||
* Argument nWidth: width of playfield (4 <= n <= 16) |
|||
* Argument nHeight: height of playfield (4 <= n <= 124) |
|||
* Return value: pointer to a newly created playfield |
|||
*/ |
|||
tetris_playfield_t *tetris_playfield_construct(int8_t nWidth, |
|||
int8_t nHeight) |
|||
{ |
|||
assert((nWidth >= 4) && (nWidth <= 16)); |
|||
assert((nHeight >= 4) && (nHeight <= 124)); |
|||
|
|||
tetris_playfield_t *pPlayfield = |
|||
(tetris_playfield_t*) malloc(sizeof(tetris_playfield_t)); |
|||
|
|||
if (pPlayfield != NULL) |
|||
{ |
|||
// allocating mem for dump array
|
|||
pPlayfield->dump = (uint16_t*) calloc(nHeight, sizeof(uint16_t)); |
|||
|
|||
if (pPlayfield->dump != NULL) |
|||
{ |
|||
// setting desired attributes
|
|||
pPlayfield->nWidth = nWidth; |
|||
pPlayfield->nHeight = nHeight; |
|||
tetris_playfield_reset(pPlayfield); |
|||
|
|||
return pPlayfield; |
|||
} |
|||
else |
|||
{ |
|||
free(pPlayfield); |
|||
pPlayfield = NULL; |
|||
} |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_destruct
|
|||
* Description: destructs a playfield |
|||
* Argument pPl: pointer to the playfield to be destructed |
|||
* Return value: void |
|||
*/ |
|||
void tetris_playfield_destruct(tetris_playfield_t *pPl) |
|||
{ |
|||
assert(pPl != NULL); |
|||
|
|||
// if memory for the dump array has been allocated, free it
|
|||
if (pPl->dump != NULL) |
|||
{ |
|||
free(pPl->dump); |
|||
} |
|||
free(pPl); |
|||
} |
|||
|
|||
|
|||
/*******************************
|
|||
* playfield related functions * |
|||
*******************************/ |
|||
|
|||
/* Function: tetris_playfield_reset
|
|||
* Description: resets playfield to begin a new game |
|||
* Argument pPl: playfield to perform action on |
|||
* Return value: void |
|||
*/ |
|||
void tetris_playfield_reset(tetris_playfield_t *pPl) |
|||
{ |
|||
assert(pPl != NULL); |
|||
|
|||
pPl->pPiece = NULL; |
|||
pPl->nColumn = 0; |
|||
pPl->nRow = 0; |
|||
pPl->nRowMask = 0; |
|||
|
|||
// clear dump if it has been allocated in memory
|
|||
if (pPl->dump != NULL) |
|||
{ |
|||
memset(pPl->dump, 0, pPl->nHeight); |
|||
} |
|||
|
|||
pPl->status = TETRIS_PFS_READY; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_insertPiece
|
|||
* Description: inserts a new piece |
|||
* Argument pPl: playfield to perform action on |
|||
* Argument pPiece: piece to be inserted |
|||
* Argument ppOldPiece: [out] indirect pointer to former piece for deallocation |
|||
* Return value: void |
|||
*/ |
|||
void tetris_playfield_insertPiece(tetris_playfield_t *pPl, |
|||
tetris_piece_t *pPiece, |
|||
tetris_piece_t** ppOldPiece) |
|||
{ |
|||
assert((pPl != NULL) && (pPiece != NULL) && (ppOldPiece != NULL)); |
|||
|
|||
// a piece can only be inserted in state TETRIS_PFS_READY
|
|||
assert(pPl->status == TETRIS_PFS_READY); |
|||
|
|||
// row mask is now meaningless
|
|||
pPl->nRowMask = 0; |
|||
|
|||
// replace old piece
|
|||
*ppOldPiece = pPl->pPiece; |
|||
pPl->pPiece = pPiece; |
|||
|
|||
// set horizontal start position (in the middle of the top line)
|
|||
pPl->nColumn = (pPl->nWidth - 2) / 2; |
|||
|
|||
// set vertical start position (first piece row with matter at pos. 1)
|
|||
uint16_t nPieceMap = tetris_piece_getBitmap(pPl->pPiece); |
|||
uint16_t nElementMask = 0xF000; |
|||
pPl->nRow = -3; |
|||
while ((nPieceMap & nElementMask) == 0) |
|||
{ |
|||
++pPl->nRow; |
|||
nElementMask >>= 4; |
|||
} |
|||
if (pPl->nRow < 0) |
|||
{ |
|||
++pPl->nRow; |
|||
} |
|||
|
|||
// did we already collide with something?
|
|||
if (tetris_playfield_collision(pPl, pPl->nColumn, pPl->nRow) == 1) |
|||
{ |
|||
// game over man, game over!!
|
|||
pPl->status = TETRIS_PFS_GAMEOVER; |
|||
} |
|||
else |
|||
{ |
|||
// bring it on!
|
|||
pPl->status = tetris_playfield_hoverStatus(pPl); |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_collision
|
|||
* Description: detects if piece collides with s.th. at a given position |
|||
* Argument pPl: playfield to perform action on |
|||
* Argument nColumn: column where the piece should be moved |
|||
* Argument nRow: row where the piece should be moved |
|||
* Return value: 1 for collision, 0 otherwise |
|||
*/ |
|||
uint8_t tetris_playfield_collision(tetris_playfield_t *pPl, |
|||
int8_t nColumn, |
|||
int8_t nRow) |
|||
{ |
|||
assert(pPl != NULL); |
|||
|
|||
// only allow coordinates which are within sane ranges
|
|||
assert((nColumn >= -4) && (nColumn < pPl->nWidth)); |
|||
assert((nRow >= -4) && (nRow < pPl->nHeight)); |
|||
|
|||
// The rows of a piece get compared with the background one by one
|
|||
// until either a collision occures or all rows are compared. Both the
|
|||
// piece row and the part of the playfield it covers are represented in
|
|||
// 4 bits which were singled out from their corresponding uint16_t
|
|||
// values and are aligned to LSB. In case where a piece overlaps with
|
|||
// either the left or the right border we "enhance" the playfield part
|
|||
// via bit shifting and set all bits representing the border to 1.
|
|||
//
|
|||
// NOTE: LSB represents the left most position.
|
|||
uint16_t nPieceMap = tetris_piece_getBitmap(pPl->pPiece); |
|||
uint16_t nPlayfieldPart; |
|||
uint16_t nPieceRowMap; |
|||
|
|||
// negative nRow values indicate that the piece hasn't fully entered the
|
|||
// playfield yet which requires special treatment if the piece overlaps
|
|||
// with either the left or the right border
|
|||
if (nRow < 0) |
|||
{ |
|||
uint16_t nBorderMask = 0x0000; |
|||
// piece overlaps with left border
|
|||
if (nColumn < 0) |
|||
{ |
|||
nBorderMask = 0x1111 << (-nColumn - 1); |
|||
} |
|||
// piece overlaps with right border
|
|||
else if ((nColumn + 3) >= pPl->nWidth) |
|||
{ |
|||
nBorderMask = 0x8888 >> ((nColumn + 3) - pPl->nWidth); |
|||
} |
|||
// return if piece collides with border
|
|||
if ((nPieceMap & nBorderMask) != 0) |
|||
{ |
|||
return 1; |
|||
} |
|||
} |
|||
|
|||
// here we check the part which has already entered the playfield
|
|||
for (int8_t y = (nRow < 0) ? -nRow : 0; y < 4; ++y) |
|||
{ |
|||
// current piece row overlaps with lower border
|
|||
if ((y + nRow) >= pPl->nHeight) |
|||
{ |
|||
// all 4 bits represent the lower border
|
|||
nPlayfieldPart = 0x000F; |
|||
} |
|||
// piece overlaps with left border
|
|||
else if (nColumn < 0) |
|||
{ |
|||
// clear all bits we are not interested in
|
|||
nPlayfieldPart = (pPl->dump[y + nRow] & (0x000F >> -nColumn)); |
|||
// add zeros to the left (the bits "behind" the left border)
|
|||
nPlayfieldPart <<= -nColumn; |
|||
// set bits beyond left border to 1
|
|||
nPlayfieldPart |= 0x000F >> (4 + nColumn); |
|||
} |
|||
// piece overlaps with right border
|
|||
else if ((nColumn + 3) >= pPl->nWidth) |
|||
{ |
|||
// align the bits we are interested in to LSB
|
|||
// (thereby clearing the rest)
|
|||
nPlayfieldPart = pPl->dump[y + nRow] >> nColumn; |
|||
// set bits beyond right border to 1
|
|||
nPlayfieldPart |= 0xFFF8 >> (nColumn + 3 - pPl->nWidth); |
|||
} |
|||
// current row neither overlaps with left, right nor lower border
|
|||
else |
|||
{ |
|||
// clear all bits we are not interested in and align the
|
|||
// remaing row to LSB
|
|||
nPlayfieldPart = |
|||
(pPl->dump[y + nRow] & (0x000F << nColumn)) >> nColumn; |
|||
} |
|||
|
|||
// clear all bits of the piece we are not interested in and
|
|||
// align the remaing row to LSB
|
|||
nPieceRowMap = (nPieceMap & (0x000F << (y << 2))) >> (y << 2); |
|||
|
|||
// finally check for a collision
|
|||
if ((nPlayfieldPart & nPieceRowMap) != 0) |
|||
{ |
|||
return 1; |
|||
} |
|||
} |
|||
|
|||
// if we reach here, no collision was detected
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_advancePiece
|
|||
* Description: lowers piece by one row or finally docks it |
|||
* Argument pPl: playfield to perform action on |
|||
* Return value: void |
|||
*/ |
|||
void tetris_playfield_advancePiece(tetris_playfield_t *pPl) |
|||
{ |
|||
assert(pPl != NULL); |
|||
|
|||
// a piece can only be lowered if it is hovering or gliding
|
|||
assert ((pPl->status == TETRIS_PFS_HOVERING) || |
|||
(pPl->status == TETRIS_PFS_GLIDING)); |
|||
|
|||
if (tetris_playfield_collision(pPl, pPl->nColumn, pPl->nRow + 1)) |
|||
{ |
|||
uint16_t nPiece = tetris_piece_getBitmap(pPl->pPiece); |
|||
|
|||
// Is the playfield filled up?
|
|||
if ((pPl->nRow < 0) && (nPiece & (0x0FFF >> ((3 + pPl->nRow) << 2))) != 0) |
|||
{ |
|||
pPl->status = TETRIS_PFS_GAMEOVER; |
|||
} |
|||
else |
|||
{ |
|||
// determine valid start point for dump index
|
|||
int8_t nStartRow = ((pPl->nRow + 3) < pPl->nHeight) ? |
|||
(pPl->nRow + 3) : pPl->nHeight - 1; |
|||
for (int8_t i = nStartRow; i >= pPl->nRow; --i) |
|||
{ |
|||
int8_t y = i - pPl->nRow; |
|||
|
|||
// clear all bits of the piece we are not interested in and
|
|||
// align the rest to LSB
|
|||
uint16_t nPieceMap = (nPiece & (0x000F << (y << 2))) >> (y << 2); |
|||
// shift the remaining content to the current column
|
|||
if (pPl->nColumn >= 0) |
|||
{ |
|||
nPieceMap <<= pPl->nColumn; |
|||
} |
|||
else |
|||
{ |
|||
nPieceMap >>= -pPl->nColumn; |
|||
} |
|||
// embed piece in playfield
|
|||
pPl->dump[i] |= nPieceMap; |
|||
} |
|||
|
|||
// the piece has finally been docked
|
|||
pPl->status = TETRIS_PFS_DOCKED; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
// since there is no collision the piece may continue its travel
|
|||
// to the ground...
|
|||
pPl->nRow++; |
|||
|
|||
// are we gliding?
|
|||
pPl->status = tetris_playfield_hoverStatus(pPl); |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_movePiece
|
|||
* Description: moves piece to the given direction |
|||
* Argument pPl: playfield to perform action on |
|||
* Argument direction: direction (see tetris_playfield_direction_t) |
|||
* Return value: 1 if piece could be moved, 0 otherwise |
|||
*/ |
|||
uint8_t tetris_playfield_movePiece(tetris_playfield_t *pPl, |
|||
tetris_playfield_direction_t direction) |
|||
{ |
|||
assert(pPl != NULL); |
|||
|
|||
// a piece can only be moved if it is still hovering or gliding
|
|||
assert((pPl->status == TETRIS_PFS_HOVERING) || |
|||
(pPl->status == TETRIS_PFS_GLIDING)); |
|||
|
|||
int8_t nOffset = (direction == TETRIS_PFD_LEFT) ? -1 : 1; |
|||
if (tetris_playfield_collision(pPl, pPl->nColumn + nOffset, pPl->nRow) == 0) |
|||
{ |
|||
pPl->nColumn += nOffset; |
|||
|
|||
// are we gliding?
|
|||
pPl->status = tetris_playfield_hoverStatus(pPl); |
|||
return 1; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_rotatePiece
|
|||
* Description: rotates piece to the given direction |
|||
* Argument pPl: playfield to perform action on |
|||
* Argument r: type of rotation (see tetris_piece_rotation_t) |
|||
* Return value: 1 if piece could be rotated, 0 otherwise |
|||
*/ |
|||
uint8_t tetris_playfield_rotatePiece(tetris_playfield_t *pPl, |
|||
tetris_piece_rotation_t rotation) |
|||
{ |
|||
assert(pPl != NULL); |
|||
|
|||
// a piece can only be rotation if it is still hovering or gliding
|
|||
assert((pPl->status == TETRIS_PFS_HOVERING) || |
|||
(pPl->status == TETRIS_PFS_GLIDING)); |
|||
|
|||
tetris_piece_rotate(pPl->pPiece, rotation); |
|||
|
|||
// does the rotated piece cause a collision?
|
|||
if (tetris_playfield_collision(pPl, pPl->nColumn, pPl->nRow) != 0) |
|||
{ |
|||
// in that case we revert the rotation
|
|||
if (rotation == TETRIS_PC_ROT_CW) |
|||
{ |
|||
tetris_piece_rotate(pPl->pPiece, TETRIS_PC_ROT_CCW); |
|||
} |
|||
else |
|||
{ |
|||
tetris_piece_rotate(pPl->pPiece, TETRIS_PC_ROT_CW); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
// are we gliding?
|
|||
pPl->status = tetris_playfield_hoverStatus(pPl); |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_removeCompletedLines
|
|||
* Description: removes completed lines (if any) and lowers the dump |
|||
* Argument pPl: playfield to perform action on |
|||
* Return value: void |
|||
*/ |
|||
void tetris_playfield_removeCompleteLines(tetris_playfield_t *pPl) |
|||
{ |
|||
assert(pPl != NULL); |
|||
|
|||
// rows can only be removed if we are in state TETRIS_PFS_DOCKED
|
|||
assert(pPl->status == TETRIS_PFS_DOCKED); |
|||
|
|||
// bit mask of a full row
|
|||
uint16_t nFullRow = 0xFFFF >> (16 - pPl->nWidth); |
|||
|
|||
// bit mask (only 4 bits) that tells us if the n-th row after the
|
|||
// current nRow is complete (n-th bit set to 1, LSB represents nRow itself)
|
|||
uint8_t nRowMask = 0; |
|||
|
|||
// determine sane start and stop values for the dump' index
|
|||
int8_t nStartRow = |
|||
((pPl->nRow + 3) >= pPl->nHeight) ? pPl->nHeight - 1 : pPl->nRow + 3; |
|||
int8_t nStopRow = (pPl->nRow < 0) ? 0 : pPl->nRow; |
|||
|
|||
// dump index variables
|
|||
// for incomplete rows, both variables will be decremented
|
|||
// for complete rows, only i gets decremented
|
|||
int8_t nLowestRow = nStartRow; |
|||
|
|||
// this loop only considers rows which are affected by the piece
|
|||
for (int8_t i = nStartRow; i >= nStopRow; --i) |
|||
{ |
|||
// is current row a full row?
|
|||
if ((nFullRow & pPl->dump[i]) == nFullRow) |
|||
{ |
|||
// set corresponding bit for the row mask
|
|||
// nRowMask |= 0x08 >> (nStartRow - i);
|
|||
nRowMask |= 0x01 << (i - pPl->nRow); |
|||
} |
|||
else |
|||
{ |
|||
// if nLowestRow and i differ, the dump has to be shifted
|
|||
if (i < nLowestRow) |
|||
{ |
|||
pPl->dump[nLowestRow] = pPl->dump[i]; |
|||
} |
|||
--nLowestRow; |
|||
} |
|||
} |
|||
|
|||
// if rows have been removed, this loop shifts the rest of the dump
|
|||
uint8_t nComplete = nLowestRow - nStopRow + 1; |
|||
if (nComplete > 0) |
|||
{ |
|||
for (int8_t i = nStopRow - 1; nLowestRow >= 0; --i) |
|||
{ |
|||
// is the row we are copying from below the upper border?
|
|||
if (i >= 0) |
|||
{ |
|||
// just copy from that row
|
|||
pPl->dump[nLowestRow] = pPl->dump[i]; |
|||
} |
|||
else |
|||
{ |
|||
// rows above the upper border are always empty
|
|||
pPl->dump[nLowestRow] = 0; |
|||
} |
|||
--nLowestRow; |
|||
} |
|||
} |
|||
|
|||
// ready to get the next piece
|
|||
pPl->status = TETRIS_PFS_READY; |
|||
|
|||
pPl->nRowMask = nRowMask; |
|||
} |
|||
|
|||
|
|||
/*****************
|
|||
* get functions * |
|||
*****************/ |
|||
|
|||
/* Function: tetris_playfield_getWidth
|
|||
* Description: returns the width of the playfield |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: width of the playfield |
|||
*/ |
|||
int8_t tetris_playfield_getWidth(tetris_playfield_t *pPl) |
|||
{ |
|||
assert(pPl != NULL); |
|||
return pPl->nWidth; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_getHeight
|
|||
* Description: returns the height of the playfield |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: height of the playfield |
|||
*/ |
|||
int8_t tetris_playfield_getHeight(tetris_playfield_t *pPl) |
|||
{ |
|||
assert(pPl != NULL); |
|||
return pPl->nHeight; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_getPiece
|
|||
* Description: returns the currently falling piece |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: pointer to the currently falling piece |
|||
*/ |
|||
tetris_piece_t *tetris_playfield_getPiece(tetris_playfield_t *pPl) |
|||
{ |
|||
assert(pPl != NULL); |
|||
return pPl->pPiece; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_getColumn
|
|||
* Description: returns the column of the currently falling piece |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: column of the currently falling piece |
|||
*/ |
|||
int8_t tetris_playfield_getColumn(tetris_playfield_t *pPl) |
|||
{ |
|||
assert(pPl != NULL); |
|||
return pPl->nColumn; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_getRow
|
|||
* Description: returns the row of the currently falling piece |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: row of the currently falling piece |
|||
*/ |
|||
int8_t tetris_playfield_getRow(tetris_playfield_t *pPl) |
|||
{ |
|||
assert(pPl != NULL); |
|||
return pPl->nRow; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_getRowMask
|
|||
* Description: returns the row mask relative to nRow |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: the first 4 bits indicate which lines (relative to nRow) |
|||
* have been removed if we are in status TETRIS_PFS_READY |
|||
* LSB is the highest line |
|||
*/ |
|||
uint8_t tetris_playfield_getRowMask(tetris_playfield_t *pPl) |
|||
{ |
|||
assert(pPl != NULL); |
|||
return pPl->nRowMask; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_getStatus
|
|||
* Description: returns the status of the playfield |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: status of the playfield (see tetris_playfield_status_t) |
|||
*/ |
|||
tetris_playfield_status_t tetris_playfield_getStatus(tetris_playfield_t *pPl) |
|||
{ |
|||
assert(pPl != NULL); |
|||
return pPl->status; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_playfield_getDumpRow
|
|||
* Description: returns the given row of the dump (as bitmap) |
|||
* Argument pPl: the playfield we want information from |
|||
* Argument nRow: the number of the row (0 <= nRow < height of playfield) |
|||
* Return value: bitmap of the requested row (LSB is leftmost column) |
|||
*/ |
|||
uint16_t tetris_playfield_getDumpRow(tetris_playfield_t *pPl, |
|||
int8_t nRow) |
|||
{ |
|||
assert(pPl != NULL); |
|||
assert((0 <= nRow) && (nRow < pPl->nHeight)); |
|||
return pPl->dump[nRow]; |
|||
} |
|||
|
@ -0,0 +1,213 @@ |
|||
#ifndef TETRIS_PLAYFIELD_H_ |
|||
#define TETRIS_PLAYFIELD_H_ |
|||
|
|||
#include <inttypes.h> |
|||
#include "piece.h" |
|||
|
|||
|
|||
/*********
|
|||
* types * |
|||
*********/ |
|||
|
|||
// directions to which a piece can be moved
|
|||
typedef enum tetris_playfield_direction_t |
|||
{ |
|||
TETRIS_PFD_LEFT, |
|||
TETRIS_PFD_RIGHT |
|||
} |
|||
tetris_playfield_direction_t; |
|||
|
|||
|
|||
// status of the playfield
|
|||
typedef enum tetris_playfield_status_t |
|||
{ |
|||
TETRIS_PFS_READY, // ready to get next piece
|
|||
TETRIS_PFS_HOVERING, // piece is still hovering
|
|||
TETRIS_PFS_GLIDING, // piece is gliding on the dump
|
|||
TETRIS_PFS_DOCKED, // piece has been docked
|
|||
TETRIS_PFS_GAMEOVER // playfield is filled up
|
|||
} |
|||
tetris_playfield_status_t; |
|||
|
|||
|
|||
// tetris_playfield_t
|
|||
typedef struct tetris_playfield_t |
|||
{ |
|||
int8_t nWidth; // width of playfield
|
|||
int8_t nHeight; // height of playfield
|
|||
tetris_piece_t *pPiece; // currently falling piece
|
|||
int8_t nColumn; // horz. piece pos. (0 is left)
|
|||
int8_t nRow; // vert. piece pos. (0 is top)
|
|||
uint8_t nRowMask; // removed lines relative to nRow (bitmap)
|
|||
tetris_playfield_status_t status; // status
|
|||
uint16_t *dump; // playfield itself
|
|||
} |
|||
tetris_playfield_t; |
|||
|
|||
|
|||
/****************************
|
|||
* construction/destruction * |
|||
****************************/ |
|||
|
|||
/* Function: tetris_playfield_construct
|
|||
* Description: constructs a playfield with the given diemensions |
|||
* Argument nWidth: width of playfield (4 <= n <= 16) |
|||
* Argument nHeight: height of playfield (4 <= n <= 124) |
|||
* Return value: pointer to a newly created playfield |
|||
*/ |
|||
tetris_playfield_t *tetris_playfield_construct(int8_t nWidth, int8_t nHeight); |
|||
|
|||
|
|||
/* Function: tetris_playfield_destruct
|
|||
* Description: destructs a playfield |
|||
* Argument pPl: pointer to the playfield to be destructed |
|||
* Return value: void |
|||
*/ |
|||
void tetris_playfield_destruct(tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/*******************************
|
|||
* playfield related functions * |
|||
*******************************/ |
|||
|
|||
/* Function: tetris_playfield_reset
|
|||
* Description: resets playfield to begin a new game |
|||
* Argument pPl: playfield to perform action on |
|||
* Return value: void |
|||
*/ |
|||
void tetris_playfield_reset(tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/* Function: tetris_playfield_insertPiece
|
|||
* Description: inserts a new piece |
|||
* Argument pPl: playfield to perform action on |
|||
* Argument pPiece: piece to be inserted |
|||
* Argument ppOldPiece: [out] indirect pointer to former piece for deallocation |
|||
* Return value: void |
|||
*/ |
|||
void tetris_playfield_insertPiece(tetris_playfield_t *pPl, |
|||
tetris_piece_t *pPiece, |
|||
tetris_piece_t** ppOldPiece); |
|||
|
|||
|
|||
/* Function: tetris_playfield_collision
|
|||
* Description: detects if piece collides with s.th. at a given position |
|||
* Argument pPl: playfield to perform action on |
|||
* Argument nColumn: column where the piece should be moved |
|||
* Argument nRow: row where the piece should be moved |
|||
* Return value: 1 for collision, 0 otherwise |
|||
*/ |
|||
uint8_t tetris_playfield_collision(tetris_playfield_t *pPl, |
|||
int8_t nColumn, |
|||
int8_t nRow); |
|||
|
|||
|
|||
/* Function: tetris_playfield_advancePiece
|
|||
* Description: lowers piece by one row or finally docks it |
|||
* Argument pPl: playfield to perform action on |
|||
* Return value: void |
|||
*/ |
|||
void tetris_playfield_advancePiece(tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/* Function: tetris_playfield_movePiece
|
|||
* Description: moves piece to the given direction |
|||
* Argument pPl: playfield to perform action on |
|||
* Argument direction: direction (see tetris_playfield_direction_t) |
|||
* Return value: 1 if piece could be moved, 0 otherwise |
|||
*/ |
|||
uint8_t tetris_playfield_movePiece(tetris_playfield_t *pPl, |
|||
tetris_playfield_direction_t direction); |
|||
|
|||
|
|||
/* Function: tetris_playfield_rotatePiece
|
|||
* Description: rotates piece to the given direction |
|||
* Argument pPl: playfield to perform action on |
|||
* Argument r: type of rotation (see tetris_piece_rotation_t) |
|||
* Return value: 1 if piece could be rotated, 0 otherwise |
|||
*/ |
|||
uint8_t tetris_playfield_rotatePiece(tetris_playfield_t *pPl, |
|||
tetris_piece_rotation_t rotation); |
|||
|
|||
|
|||
/* Function: tetris_playfield_removeCompletedLines
|
|||
* Description: removes completed lines (if any) and lowers the dump |
|||
* Argument pPl: playfield to perform action on |
|||
* Return value: void |
|||
*/ |
|||
void tetris_playfield_removeCompleteLines(tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/*****************
|
|||
* get functions * |
|||
*****************/ |
|||
|
|||
/* Function: tetris_playfield_getWidth
|
|||
* Description: returns the width of the playfield |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: width of the playfield |
|||
*/ |
|||
int8_t tetris_playfield_getWidth(tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/* Function: tetris_playfield_getHeight
|
|||
* Description: returns the height of the playfield |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: height of the playfield |
|||
*/ |
|||
int8_t tetris_playfield_getHeight(tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/* Function: tetris_playfield_getPiece
|
|||
* Description: returns the currently falling piece |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: pointer to the currently falling piece |
|||
*/ |
|||
tetris_piece_t *tetris_playfield_getPiece(tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/* Function: tetris_playfield_getColumn
|
|||
* Description: returns the column of the currently falling piece |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: column of the currently falling piece |
|||
*/ |
|||
int8_t tetris_playfield_getColumn(tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/* Function: tetris_playfield_getRow
|
|||
* Description: returns the row of the currently falling piece |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: row of the currently falling piece |
|||
*/ |
|||
int8_t tetris_playfield_getRow(tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/* Function: tetris_playfield_getRowMask
|
|||
* Description: returns the row mask relative to nRow |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: the first 4 bits indicate which lines (relative to nRow) |
|||
* have been removed if we are in status TETRIS_PFS_READY |
|||
*/ |
|||
uint8_t tetris_playfield_getRowMask(tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/* Function: tetris_playfield_getStatus
|
|||
* Description: returns the status of the playfield |
|||
* Argument pPl: the playfield we want information from |
|||
* Return value: status of the playfield (see tetris_playfield_status_t) |
|||
*/ |
|||
tetris_playfield_status_t tetris_playfield_getStatus(tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/* Function: tetris_playfield_getDumpRow
|
|||
* Description: returns the given row of the dump (as bitmap) |
|||
* Argument pPl: the playfield we want information from |
|||
* Argument nRow: the number of the row (0 <= nRow <= 124) |
|||
* Return value: bitmap of the requested row (LSB is leftmost column) |
|||
*/ |
|||
uint16_t tetris_playfield_getDumpRow(tetris_playfield_t *pPl, |
|||
int8_t nRow); |
|||
|
|||
|
|||
#endif /*TETRIS_PLAYFIELD_H_*/ |
|||
|
@ -0,0 +1,421 @@ |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <stdio.h> |
|||
#include <assert.h> |
|||
#include <inttypes.h> |
|||
#include "../config.h" |
|||
#include "../pixel.h" |
|||
#include "../util.h" |
|||
#include "../scrolltext.h" |
|||
#include "logic.h" |
|||
#include "piece.h" |
|||
#include "playfield.h" |
|||
#include "view.h" |
|||
|
|||
/* the API simulator and the real API have different named wait functions */ |
|||
#ifdef __AVR__ |
|||
#define WAIT(ms) wait(ms) |
|||
#else |
|||
#define WAIT(ms) myWait(ms) |
|||
#endif |
|||
|
|||
|
|||
/***********
|
|||
* defines * |
|||
***********/ |
|||
|
|||
// how often should the border blink (to indicate level up)
|
|||
#define TETRIS_VIEW_BORDER_BLINK_COUNT 2 |
|||
// amount of time (in ms) between border color changes
|
|||
#define TETRIS_VIEW_BORDER_BLINK_DELAY 100 |
|||
|
|||
// how often should the lines blink when they get removed
|
|||
#define TETRIS_VIEW_LINE_BLINK_COUNT 3 |
|||
// amount of time (in ms) between line color changes
|
|||
#define TETRIS_VIEW_LINE_BLINK_DELAY 75 |
|||
|
|||
// colors of game elements
|
|||
#define TETRIS_VIEW_COLORSPACE 0 |
|||
#define TETRIS_VIEW_COLORBORDER 1 |
|||
#define TETRIS_VIEW_COLORFADE 2 |
|||
#define TETRIS_VIEW_COLORPIECE 3 |
|||
|
|||
|
|||
/***************************
|
|||
* non-interface functions * |
|||
***************************/ |
|||
|
|||
/* Function: tetris_view_getPieceColor
|
|||
* Description: helper function to dim the piece color if game is paused |
|||
* Argument pV: pointer to the view whose pause status is of interest |
|||
* Return value: void |
|||
*/ |
|||
uint8_t tetris_view_getPieceColor (tetris_view_t *pV) |
|||
{ |
|||
if (pV->modeCurrent == TETRIS_VIMO_RUNNING) |
|||
{ |
|||
return TETRIS_VIEW_COLORPIECE; |
|||
} |
|||
else |
|||
{ |
|||
return TETRIS_VIEW_COLORBORDER; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_view_drawDump
|
|||
* Description: redraws the dump and the falling piece (if necessary) |
|||
* Argument pV: pointer to the view on which the dump should be drawn |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_drawDump(tetris_view_t *pV) |
|||
{ |
|||
assert(pV->pPl != NULL); |
|||
if (tetris_playfield_getRow(pV->pPl) <= -4) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
int8_t nPieceRow = tetris_playfield_getRow(pV->pPl); |
|||
|
|||
// only redraw dump completely if the view mode has been changed
|
|||
int8_t nStartRow; |
|||
if (pV->modeCurrent == pV->modeOld) |
|||
{ |
|||
nStartRow = ((nPieceRow + 3) < 16) ? (nPieceRow + 3) : 15; |
|||
} |
|||
else |
|||
{ |
|||
nStartRow = 15; |
|||
} |
|||
|
|||
uint16_t nRowMap; |
|||
uint16_t nElementMask; |
|||
|
|||
tetris_playfield_status_t status = tetris_playfield_getStatus(pV->pPl); |
|||
for (int8_t nRow = nStartRow; nRow >= 0; --nRow) |
|||
{ |
|||
nRowMap = tetris_playfield_getDumpRow(pV->pPl, nRow); |
|||
|
|||
// if a piece is hovering or gliding it needs to be drawn
|
|||
if ((status == TETRIS_PFS_HOVERING) || (status == TETRIS_PFS_GLIDING) || |
|||
(status == TETRIS_PFS_GAMEOVER)) |
|||
{ |
|||
if ((nRow >= nPieceRow) && (nRow <= nPieceRow + 3)) |
|||
{ |
|||
int8_t y = nRow - nPieceRow; |
|||
int8_t nColumn = tetris_playfield_getColumn(pV->pPl); |
|||
uint16_t nPieceMap = |
|||
tetris_piece_getBitmap(tetris_playfield_getPiece(pV->pPl)); |
|||
// clear all bits of the piece we are not interested in and
|
|||
// align the remaining row to LSB
|
|||
nPieceMap = (nPieceMap & (0x000F << (y << 2))) >> (y << 2); |
|||
// shift remaining part to current column
|
|||
if (nColumn >= 0) |
|||
{ |
|||
nPieceMap <<= nColumn; |
|||
} |
|||
else |
|||
{ |
|||
nPieceMap >>= -nColumn; |
|||
} |
|||
// cut off unwanted stuff
|
|||
nPieceMap &= 0x03ff; |
|||
// finally embed piece into the view
|
|||
nRowMap |= nPieceMap; |
|||
} |
|||
} |
|||
|
|||
nElementMask = 0x0001; |
|||
|
|||
for (int8_t x = 0; x < 10; ++x) |
|||
{ |
|||
unsigned char nColor; |
|||
if ((nRowMap & nElementMask) != 0) |
|||
{ |
|||
nColor = tetris_view_getPieceColor(pV); |
|||
} |
|||
else |
|||
{ |
|||
nColor = TETRIS_VIEW_COLORSPACE; |
|||
} |
|||
setpixel((pixel){14-x,nRow}, nColor); |
|||
nElementMask <<= 1; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_view_drawPreviewPiece
|
|||
* Description: redraws the preview window |
|||
* Argument pV: pointer to the view on which the piece should be drawn |
|||
* Argmument pPc: pointer to the piece for the preview window (may be NULL) |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_drawPreviewPiece(tetris_view_t *pV, tetris_piece_t *pPc) |
|||
{ |
|||
if (pPc != NULL) |
|||
{ |
|||
uint8_t nColor; |
|||
uint16_t nElementMask = 0x0001; |
|||
uint16_t nPieceMap; |
|||
if (pV->modeCurrent == TETRIS_VIMO_RUNNING) |
|||
{ |
|||
nPieceMap = tetris_piece_getBitmap(pPc); |
|||
} |
|||
else |
|||
{ |
|||
nPieceMap = 0x26a6; |
|||
} |
|||
|
|||
for (uint8_t y = 0; y < 4; ++y) |
|||
{ |
|||
for (uint8_t x = 0; x < 4; ++x) |
|||
{ |
|||
if ((nPieceMap & nElementMask) != 0) |
|||
{ |
|||
nColor = TETRIS_VIEW_COLORPIECE; |
|||
} |
|||
else |
|||
{ |
|||
nColor = TETRIS_VIEW_COLORSPACE; |
|||
} |
|||
setpixel((pixel) {3 - x, y + 6}, nColor); |
|||
nElementMask <<= 1; |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (uint8_t y = 0; y < 4; ++y) |
|||
{ |
|||
for (uint8_t x = 0; x < 4; ++x) |
|||
{ |
|||
setpixel((pixel) {3 - x, y + 6}, TETRIS_VIEW_COLORSPACE); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_view_drawBorders
|
|||
* Description: draws borders in the given color |
|||
* Argument nColor: the color for the border |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_drawBorders(uint8_t nColor) |
|||
{ |
|||
// drawing playfield
|
|||
uint8_t x, y; |
|||
for (y = 0; y < 16; ++y) |
|||
{ |
|||
setpixel((pixel){4, y}, nColor); |
|||
setpixel((pixel){15, y}, nColor); |
|||
} |
|||
for (y = 0; y < 5; ++y) |
|||
{ |
|||
for (x = 0; x <= 3; ++x){ |
|||
setpixel((pixel){x, y}, nColor); |
|||
setpixel((pixel){x, y + 11}, nColor); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_view_blinkBorders
|
|||
* Description: lets the borders blink to notify player of a level change |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_blinkBorders() |
|||
{ |
|||
for (uint8_t i = 0; i < TETRIS_VIEW_BORDER_BLINK_COUNT; ++i) |
|||
{ |
|||
tetris_view_drawBorders(TETRIS_VIEW_COLORPIECE); |
|||
WAIT(TETRIS_VIEW_BORDER_BLINK_DELAY); |
|||
tetris_view_drawBorders(TETRIS_VIEW_COLORBORDER); |
|||
WAIT(TETRIS_VIEW_BORDER_BLINK_DELAY); |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_view_blinkLines
|
|||
* Description: lets complete lines blink to emphasize their removal |
|||
* Argmument pPl: pointer to the playfield whose complete lines should blink |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_blinkLines(tetris_playfield_t *pPl) |
|||
{ |
|||
// reduce necessity of pointer arithmetic
|
|||
int8_t nRow = tetris_playfield_getRow(pPl); |
|||
uint8_t nRowMask = tetris_playfield_getRowMask(pPl); |
|||
|
|||
// don't try to draw below the border
|
|||
int8_t nDeepestRowOffset = ((nRow + 3) < tetris_playfield_getHeight(pPl) ? |
|||
3 : tetris_playfield_getHeight(pPl) - (nRow + 1)); |
|||
|
|||
// this loop controls how often the lines should blink
|
|||
for (uint8_t i = 0; i < TETRIS_VIEW_LINE_BLINK_COUNT; ++i) |
|||
{ |
|||
// this loop determines the color of the line to be drawn
|
|||
for (uint8_t nColIdx = 0; nColIdx < 2; ++nColIdx) |
|||
{ |
|||
// iterate through the possibly complete lines
|
|||
for (uint8_t j = 0; j <= nDeepestRowOffset; ++j) |
|||
{ |
|||
// is current line a complete line?
|
|||
if ((nRowMask & (0x01 << j)) != 0) |
|||
{ |
|||
// draw line in current color
|
|||
uint8_t y = nRow + j; |
|||
for (uint8_t x = 0; x < 10; ++x) |
|||
{ |
|||
|
|||
uint8_t nColor = (nColIdx == 0 ? TETRIS_VIEW_COLORFADE |
|||
: TETRIS_VIEW_COLORPIECE); |
|||
setpixel((pixel){14 - x, y}, nColor); |
|||
} |
|||
} |
|||
} |
|||
// wait a few ms to make the blink effect visible
|
|||
WAIT(TETRIS_VIEW_LINE_BLINK_DELAY); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
/****************************
|
|||
* construction/destruction * |
|||
****************************/ |
|||
|
|||
/* Function: tetris_view_construct
|
|||
* Description: constructs a view for André's borg |
|||
* Argument pPl: pointer to logic object which should be observed |
|||
* Argument pPl: pointer to playfield which should be observed |
|||
* Return value: pointer to a newly created view |
|||
*/ |
|||
tetris_view_t *tetris_view_construct(tetris_logic_t *pLogic, |
|||
tetris_playfield_t *pPl) |
|||
{ |
|||
// memory allocation
|
|||
assert((pLogic != NULL) && (pPl != NULL)); |
|||
tetris_view_t *pView = |
|||
(tetris_view_t *) malloc(sizeof(tetris_view_t)); |
|||
assert(pView != NULL); |
|||
|
|||
// init
|
|||
memset(pView, 0, sizeof(tetris_view_t)); |
|||
pView->pLogic = pLogic; |
|||
pView->pPl = pPl; |
|||
pView->modeCurrent = TETRIS_VIMO_RUNNING; |
|||
pView->modeOld = TETRIS_VIMO_RUNNING; |
|||
|
|||
// drawing some first stuff
|
|||
clear_screen(0); |
|||
tetris_view_drawBorders(TETRIS_VIEW_COLORBORDER); |
|||
|
|||
return pView; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_view_destruct
|
|||
* Description: destructs a view |
|||
* Argument pView: pointer to the view which should be destructed |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_destruct(tetris_view_t *pView) |
|||
{ |
|||
assert(pView != NULL); |
|||
free(pView); |
|||
} |
|||
|
|||
|
|||
/***************************
|
|||
* view related functions * |
|||
***************************/ |
|||
|
|||
/* Function: tetris_view_getDimensions
|
|||
* Description: destructs a view |
|||
* Argument w: [out] pointer to an int8_t to store the playfield width |
|||
* Argument h: [out] pointer to an int8_t to store the playfield height |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_getDimensions(int8_t *w, |
|||
int8_t *h) |
|||
{ |
|||
assert((w != NULL) && (h != NULL)); |
|||
*w = 10; |
|||
*h = 16; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_view_setViewMode
|
|||
* Description: sets the view mode (pause or running) |
|||
* Argument pV: pointer to the view whose mode should be set |
|||
* Argument vm: see definition of tetris_view_mode_t |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_setViewMode(tetris_view_t *pV, tetris_view_mode_t vm) |
|||
{ |
|||
pV->modeOld = pV->modeCurrent; |
|||
pV->modeCurrent = vm; |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_view_update
|
|||
* Description: informs a view about changes in the game |
|||
* Argument pV: pointer to the view which should be updated |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_update(tetris_view_t *pV) |
|||
{ |
|||
assert(pV != NULL); |
|||
|
|||
// let complete lines blink (if there are any)
|
|||
if (tetris_playfield_getRowMask(pV->pPl) != 0) |
|||
{ |
|||
tetris_view_blinkLines(pV->pPl); |
|||
} |
|||
|
|||
// draw preview piece
|
|||
tetris_view_drawPreviewPiece(pV, tetris_logic_getPreviewPiece(pV->pLogic)); |
|||
|
|||
// draw dump
|
|||
tetris_view_drawDump(pV); |
|||
|
|||
// visual feedback to inform about a level change
|
|||
uint8_t nLevel = tetris_logic_getLevel(pV->pLogic); |
|||
if (nLevel != pV->nOldLevel) |
|||
{ |
|||
tetris_view_blinkBorders(); |
|||
pV->nOldLevel = nLevel; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Function: tetris_view_showResults
|
|||
* Description: shows results after game |
|||
* Argument pV: pointer to the view which should show the reults |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_showResults(tetris_view_t *pV) |
|||
{ |
|||
char pszResults[48]; |
|||
uint16_t nScore = tetris_logic_getScore(pV->pLogic); |
|||
uint16_t nHighscore = tetris_logic_getHighscore(pV->pLogic); |
|||
uint16_t nLines = tetris_logic_getLines(pV->pLogic); |
|||
|
|||
if (nScore <= nHighscore) |
|||
{ |
|||
snprintf(pszResults, 48 * sizeof(char), |
|||
"</#Lines %u Score %u Highscore %u", |
|||
nLines, nScore, nHighscore); |
|||
} |
|||
else |
|||
{ |
|||
snprintf(pszResults, 48 * sizeof(char), |
|||
"</#Lines %u New Highscore %u", nLines, nScore); |
|||
} |
|||
|
|||
scrolltext(pszResults); |
|||
} |
|||
|
@ -0,0 +1,95 @@ |
|||
#ifndef TETRIS_VIEW_H_ |
|||
#define TETRIS_VIEW_H_ |
|||
|
|||
#include <inttypes.h> |
|||
#include "logic.h" |
|||
#include "piece.h" |
|||
#include "playfield.h" |
|||
|
|||
|
|||
/*********
|
|||
* types * |
|||
*********/ |
|||
|
|||
// presentation modes
|
|||
typedef enum tetris_view_mode_t |
|||
{ |
|||
TETRIS_VIMO_PAUSED, |
|||
TETRIS_VIMO_RUNNING |
|||
} |
|||
tetris_view_mode_t; |
|||
|
|||
typedef struct tetris_view_t |
|||
{ |
|||
tetris_logic_t *pLogic; // associated logic object
|
|||
tetris_playfield_t *pPl; // associated playfield
|
|||
tetris_view_mode_t modeCurrent; // current presentation mode
|
|||
tetris_view_mode_t modeOld; // old presentation mode
|
|||
uint8_t nOldLevel; // helper variable to recognize level changes
|
|||
} |
|||
tetris_view_t; |
|||
|
|||
|
|||
/*****************************
|
|||
* construction/destruction * |
|||
*****************************/ |
|||
|
|||
/* Function: tetris_view_construct
|
|||
* Description: constructs a view for André's borg |
|||
* Argument pPl: pointer to logic object which should be observed |
|||
* Argument pPl: pointer to playfield which should be observed |
|||
* Return value: pointer to a newly created view |
|||
*/ |
|||
tetris_view_t *tetris_view_construct(tetris_logic_t *pLogic, |
|||
tetris_playfield_t *pPl); |
|||
|
|||
|
|||
/* Function: tetris_view_destruct
|
|||
* Description: destructs a view |
|||
* Argument pView: pointer to the view to be destructed |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_destruct(tetris_view_t *pView); |
|||
|
|||
|
|||
/***************************
|
|||
* view related functions * |
|||
***************************/ |
|||
|
|||
/* Function: tetris_view_getDimensions
|
|||
* Description: destructs a view |
|||
* Argument w: [out] pointer to an int8_t to store the playfield width |
|||
* Argument h: [out] pointer to an int8_t to store the playfield height |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_getDimensions(int8_t *w, |
|||
int8_t *h); |
|||
|
|||
|
|||
/* Function: tetris_view_setViewMode
|
|||
* Description: sets the view mode (pause or running) |
|||
* Argument pV: pointer to the view whose mode should be set |
|||
* Argument vm: see definition of tetris_view_mode_t |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_setViewMode(tetris_view_t *pV, tetris_view_mode_t vm); |
|||
|
|||
|
|||
/* Function: tetris_view_update
|
|||
* Description: informs a view about changes in the game |
|||
* Argument pV: pointer to the view which should be updated |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_update(tetris_view_t *pV); |
|||
|
|||
|
|||
/* Function: tetris_view_showResults
|
|||
* Description: shows results after game |
|||
* Argument pV: pointer to the view which should show the reults |
|||
* Return value: void |
|||
*/ |
|||
void tetris_view_showResults(tetris_view_t *pV); |
|||
|
|||
|
|||
#endif /*TETRIS_VIEW_H_*/ |
|||
|
@ -0,0 +1,13 @@ |
|||
#include "joystick.h" |
|||
#include <avr/io.h> |
|||
|
|||
unsigned char waitForFire; |
|||
|
|||
|
|||
inline void joy_init(){ |
|||
DDRB &= ~((1<<BITUP)|(1<<BITDOWN)|(1<<BITLEFT)|(1<<BITRIGHT)); |
|||
PORTB |= (1<<BITUP)|(1<<BITDOWN)|(1<<BITLEFT)|(1<<BITRIGHT); |
|||
|
|||
DDRD &= ~(1<<BITFIRE); |
|||
PORTD |= (1<<BITFIRE); |
|||
} |
@ -0,0 +1,21 @@ |
|||
#ifndef JOYSTICK_H |
|||
#define JOYSTICK_H |
|||
|
|||
#include <avr/io.h> |
|||
|
|||
unsigned char waitForFire; |
|||
void joy_init(); |
|||
|
|||
#define BITFIRE PD3 |
|||
#define BITRIGHT PB3 |
|||
#define BITLEFT PB2 |
|||
#define BITDOWN PB1 |
|||
#define BITUP PB0 |
|||
|
|||
#define JOYISFIRE (!(PIND & (1<<BITFIRE))) |
|||
#define JOYISLEFT (!(PINB & (1<<BITLEFT))) |
|||
#define JOYISRIGHT (!(PINB & (1<<BITRIGHT))) |
|||
#define JOYISDOWN (!(PINB & (1<<BITDOWN))) |
|||
#define JOYISUP (!(PINB & (1<<BITUP))) |
|||
|
|||
#endif // JOYSTICK_H
|
@ -0,0 +1,149 @@ |
|||
|
|||
#include <setjmp.h> |
|||
#include <avr/interrupt.h> |
|||
#include <stdio.h> |
|||
|
|||
#include "autoconf.h" |
|||
//#include "config.h"
|
|||
#include "scrolltext/scrolltext.h" |
|||
#include "animations/programm.h" |
|||
#include "animations/matrix.h" |
|||
#include "animations/gameoflife.h" |
|||
#include "borg_hw/borg_hw.h" |
|||
#include "can/borg_can.h" |
|||
#include "random/prng.h" |
|||
#include "random/persistentCounter.h" |
|||
#include "mcuf/mcuf.h" |
|||
#include "menu/menu.h" |
|||
#include "pixel.h" |
|||
#include "joystick.h" |
|||
|
|||
volatile unsigned char oldMode, oldOldmode, mode; |
|||
|
|||
jmp_buf newmode_jmpbuf; |
|||
|
|||
int main (void){ |
|||
clear_screen(0); |
|||
|
|||
borg_hw_init(); |
|||
|
|||
#ifdef RANDOM_SUPPORT |
|||
srandom32(percnt_get()); |
|||
percnt_inc(); |
|||
#endif |
|||
|
|||
#ifdef CAN_SUPPORT |
|||
bcan_init(); |
|||
#endif |
|||
|
|||
#ifdef JOYSTICK_SUPPORT |
|||
joy_init(); |
|||
#endif |
|||
|
|||
#ifdef UART_SUPPORT |
|||
uart_init(); |
|||
#endif |
|||
|
|||
sei(); |
|||
|
|||
// mcuf_serial_mode();
|
|||
|
|||
mode = setjmp(newmode_jmpbuf); |
|||
oldOldmode = oldMode; |
|||
waitForFire = 1; |
|||
for(;;){ |
|||
oldMode = mode; |
|||
switch(mode++) { |
|||
|
|||
#ifdef ANIMATION_SCROLLTEXT |
|||
case 1: |
|||
scrolltext(scrolltext_text); |
|||
{ char a[14]; |
|||
sprintf(a,"</# counter == %lu ", percnt_get()); |
|||
scrolltext(a); |
|||
} |
|||
break; |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_SPIRALE |
|||
case 2: |
|||
spirale(5); |
|||
break; |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_JOERN1 |
|||
case 3: |
|||
joern1(); |
|||
break; |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_SNAKE |
|||
case 4: |
|||
snake(); |
|||
break; |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_SCHACHBRETT |
|||
case 5: |
|||
schachbrett(20); |
|||
break; |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_FEUER |
|||
case 6: |
|||
feuer(); |
|||
break; |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_MATRIX |
|||
case 7: |
|||
matrix(); |
|||
break; |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_RANDOM_BRIGHT |
|||
case 8: |
|||
random_bright(200); |
|||
break; |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_GAMEOFLIFE |
|||
case 9: |
|||
gameoflife(); |
|||
break; |
|||
#endif |
|||
|
|||
case 29: |
|||
mode = 1; |
|||
break; |
|||
|
|||
#ifdef ANIMATION_TESTS |
|||
case 31: |
|||
test_level1(); |
|||
break; |
|||
case 32: |
|||
test_level2(); |
|||
break; |
|||
case 33: |
|||
test_level3(); |
|||
break; |
|||
case 35: |
|||
test1(); |
|||
while(1); |
|||
break; |
|||
#endif |
|||
|
|||
#ifdef ANIMATION_OFF |
|||
case 0xFF: |
|||
off(); |
|||
break; |
|||
#endif |
|||
|
|||
#ifdef MENU_SUPPORT |
|||
case 43: |
|||
menu(); |
|||
mode = oldOldmode; |
|||
#endif |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,2 @@ |
|||
|
|||
#define DDR(port) (*(volatile uint8_t*)((&port)-1)) |
@ -0,0 +1,76 @@ |
|||
|
|||
#include "uart.h" |
|||
#include "pixel.h" |
|||
|
|||
#define my_uart_getc uart_getc |
|||
|
|||
typedef struct |
|||
{ |
|||
uint32_t magic; |
|||
uint8_t height_h; |
|||
uint8_t height_l; |
|||
uint8_t width_h; |
|||
uint8_t width_l; |
|||
uint16_t channels; |
|||
uint16_t maxval; |
|||
uint8_t pixels[256]; |
|||
} mcuf_t; |
|||
|
|||
|
|||
static void parse_mcuf(mcuf_t * mcuf){ |
|||
if(mcuf->height_l == 8 && mcuf->width_l == 18){ |
|||
uint8_t x,y; |
|||
for(y=0;y<8;y++){ |
|||
for(x=0;x<16;x++){ |
|||
setpixel((pixel){15-x, y+4}, mcuf->pixels[y*18 + x + 1] >> 6 ); |
|||
} |
|||
} |
|||
}else if(mcuf->height_l == 16 && mcuf->width_l == 16){ |
|||
uint8_t x,y; |
|||
for(y=0;y<16;y++){ |
|||
for(x=0;x<16;x++){ |
|||
setpixel((pixel){15-x, y}, mcuf->pixels[y*16 + x] >> 6 ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
static uint8_t mcuf_magic[4] = {0x23, 0x54, 0x26, 0x66}; |
|||
|
|||
|
|||
void mcuf_serial_mode(){ |
|||
mcuf_t mcuf_packet; |
|||
uint8_t c; |
|||
|
|||
while(1){ |
|||
uint16_t count = 0; |
|||
uint8_t x; |
|||
uint16_t num_pixels; |
|||
do{ |
|||
c = my_uart_getc(); |
|||
((uint8_t*)&mcuf_packet)[count] = c; |
|||
if(c == mcuf_magic[count] ){ |
|||
count ++; |
|||
}else{ |
|||
count = 0; |
|||
} |
|||
}while(count != 4); |
|||
|
|||
for(x=0; x<4; x++){ |
|||
c = my_uart_getc(); |
|||
((uint8_t*)&mcuf_packet)[count++] = c; |
|||
} |
|||
num_pixels = (uint16_t)mcuf_packet.width_l * mcuf_packet.height_l; |
|||
if(num_pixels <= 256){ |
|||
num_pixels += 4; |
|||
while(num_pixels--){ |
|||
c = my_uart_getc(); |
|||
((uint8_t*)&mcuf_packet)[count++] = c; |
|||
} |
|||
parse_mcuf(&mcuf_packet); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
@ -0,0 +1,3 @@ |
|||
|
|||
void mcuf_serial_mode(); |
|||
|
@ -0,0 +1,272 @@ |
|||
/* A game chooser for borgs
|
|||
* by: Christian Kroll |
|||
* date: Thursday, 2008/03/16 |
|||
*/ |
|||
|
|||
#include <stdlib.h> |
|||
#include <assert.h> |
|||
#include <inttypes.h> |
|||
|
|||
// architecture dependent stuff
|
|||
#ifdef __AVR__ |
|||
#include <avr/pgmspace.h> |
|||
#define WAIT(ms) wait(ms) |
|||
#else |
|||
#define PROGMEM |
|||
#define WAIT(ms) myWait(ms) |
|||
#endif |
|||
|
|||
#include "menu.h" |
|||
#include "config.h" |
|||
#include "util.h" |
|||
#include "pixel.h" |
|||
#include "joystick.h" |
|||
#include "snake.h" |
|||
#include "tetris/logic.h" |
|||
#include "invaders2.h" |
|||
|
|||
// defines
|
|||
#define MENU_WIDTH_ICON 8 |
|||
#define MENU_HEIGHT_ICON 8 |
|||
#define MENU_WIDTH_DELIMITER 2 |
|||
#define MENU_POLL_INTERVAL 10 |
|||
#define MENU_TIMEOUT_ITERATIONS 2000 |
|||
#define MENU_WAIT_CHATTER 60 |
|||
#define MENU_WAIT_INITIAL 40 |
|||
#define MENU_WAIT_INCREMENT 0 |
|||
|
|||
#define MENU_NEXTITEM(item) ((item + 1) % MENU_ITEM_MAX) |
|||
#define MENU_PREVITEM(item) ((item + MENU_ITEM_MAX - 1) % MENU_ITEM_MAX) |
|||
|
|||
void menu() |
|||
{ |
|||
// don't let WAIT() query fire button to prevent endless circular jumps
|
|||
waitForFire = 0; |
|||
|
|||
clear_screen(0); |
|||
|
|||
// wait as long the fire button is pressed to prevent unwanted selections
|
|||
while (JOYISFIRE) |
|||
{ |
|||
WAIT(MENU_POLL_INTERVAL); |
|||
} |
|||
|
|||
// set initial menu item
|
|||
static menu_item_t miSelection = MENU_ITEM_TETRIS; |
|||
// scroll in currently selected menu item
|
|||
menu_animate(MENU_PREVITEM(miSelection), MENU_DIRECTION_LEFT); |
|||
|
|||
uint16_t nMenuIterations= MENU_TIMEOUT_ITERATIONS; |
|||
|
|||
while (1) |
|||
{ |
|||
// the user has made her/his choice
|
|||
if (JOYISFIRE) |
|||
{ |
|||
// prevent unwanted selections
|
|||
while (JOYISFIRE) |
|||
{ |
|||
WAIT(MENU_POLL_INTERVAL); |
|||
} |
|||
// work against the chatter effects of dump joysticks
|
|||
WAIT(MENU_WAIT_CHATTER); |
|||
|
|||
// call corresponding function
|
|||
switch (miSelection) |
|||
{ |
|||
case MENU_ITEM_SNAKE: |
|||
snake_game(); |
|||
break; |
|||
case MENU_ITEM_SPACEINVADERS: |
|||
borg_invaders(); |
|||
break; |
|||
case MENU_ITEM_TETRIS: |
|||
tetris(); |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
break; |
|||
} |
|||
// change selected item and do some scrolling
|
|||
else if (JOYISRIGHT) |
|||
{ |
|||
menu_animate(miSelection, MENU_DIRECTION_LEFT); |
|||
miSelection = MENU_NEXTITEM(miSelection); |
|||
nMenuIterations = MENU_TIMEOUT_ITERATIONS; |
|||
} |
|||
else if (JOYISLEFT) |
|||
{ |
|||
menu_animate(miSelection, MENU_DIRECTION_RIGHT); |
|||
miSelection = MENU_PREVITEM(miSelection); |
|||
nMenuIterations = MENU_TIMEOUT_ITERATIONS; |
|||
} |
|||
// exit menu
|
|||
else if (JOYISUP) |
|||
{ |
|||
break; |
|||
} |
|||
// return if timeout is reached
|
|||
else |
|||
{ |
|||
WAIT(MENU_POLL_INTERVAL); |
|||
if (--nMenuIterations == 0) |
|||
break; |
|||
} |
|||
} |
|||
|
|||
waitForFire = 1; |
|||
return; |
|||
} |
|||
|
|||
uint8_t menu_getIconPixel(menu_item_t item, int8_t x, int8_t y) |
|||
{ |
|||
// MSB is leftmost pixel
|
|||
static uint8_t nIcon[][8] PROGMEM = |
|||
{{0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xad, 0xa1, 0xbf}, // Snake icon
|
|||
{0x66, 0x18, 0x3c, 0x5a, 0xff, 0xbd, 0xa5, 0x18}, // Invaders icon
|
|||
{0x0f, 0x0f, 0xc3, 0xdb, 0xdb, 0xc3, 0xf0, 0xf0}}; // Tetris icon
|
|||
|
|||
// is x within the icon or do we have reached the delimiter?
|
|||
if (x < MENU_WIDTH_ICON) |
|||
{ |
|||
// return pixel
|
|||
#ifdef __AVR__ |
|||
return (0x80 >> x) & pgm_read_word(&nIcon[item][y]); |
|||
#else |
|||
return (0x80 >> x) & nIcon[item][y]; |
|||
#endif |
|||
} |
|||
else |
|||
{ |
|||
// delimiter
|
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
void menu_animate(menu_item_t miInitial, menu_direction_t direction) |
|||
{ |
|||
int16_t nWait= MENU_WAIT_INITIAL; |
|||
|
|||
// space between left border and the icon in the middle
|
|||
int8_t nWidthSide = (NUM_COLS - MENU_WIDTH_ICON) / 2; |
|||
|
|||
// determine the icon at the leftmost position
|
|||
menu_item_t mi = miInitial + MENU_ITEM_MAX; |
|||
int8_t nBack = nWidthSide / (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER); |
|||
if ((nWidthSide % (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)) != 0) |
|||
{ |
|||
++nBack; |
|||
} |
|||
mi = (mi + MENU_ITEM_MAX - (nBack % MENU_ITEM_MAX)) % MENU_ITEM_MAX; |
|||
|
|||
// start and stop offsets for the scrolling icons (both are 0 for stills)
|
|||
int8_t nStart, nStop; |
|||
if (direction == MENU_DIRECTION_STILL) |
|||
{ |
|||
nStart = 0; |
|||
nStop = 0; |
|||
} |
|||
else |
|||
{ |
|||
nStart = 1; |
|||
nStop = MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER; |
|||
} |
|||
|
|||
// draw menu screen for each offset within the nStart/nStop range
|
|||
int8_t i; |
|||
for (i = nStart; i <= nStop; ++i) |
|||
{ |
|||
int8_t nOffset; |
|||
if (direction == MENU_DIRECTION_LEFT) |
|||
nOffset = i; |
|||
else |
|||
nOffset = -i; |
|||
|
|||
// offset of the left most icon if it is cut by the left border
|
|||
int8_t nInitialSideOffset = (((MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER) |
|||
- (nWidthSide % (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER))) |
|||
+ nOffset + (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)) |
|||
% (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER); |
|||
|
|||
// an initial side offset of 0 means the leftmost icon was changed
|
|||
// if we are scrolling to the left, increment value for leftmost item
|
|||
if (direction == MENU_DIRECTION_LEFT) |
|||
{ |
|||
if (nInitialSideOffset == 0) |
|||
{ |
|||
mi = MENU_NEXTITEM(mi); |
|||
} |
|||
} |
|||
|
|||
// draw the icons from the leftmost position (line by line)
|
|||
int8_t y; |
|||
for (y = 0; y < MENU_HEIGHT_ICON; ++y) |
|||
{ |
|||
menu_item_t miCurrent = mi; |
|||
int8_t nIconOffset = nInitialSideOffset; |
|||
int8_t x; |
|||
for (x = 0; x < NUM_COLS; ++x) |
|||
{ |
|||
int8_t nPixel = menu_getIconPixel(miCurrent, nIconOffset, y); |
|||
|
|||
menu_setpixel(x, ((NUM_ROWS - MENU_HEIGHT_ICON) / 2) + y, |
|||
nPixel); |
|||
if (++nIconOffset >= (MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER)) |
|||
{ |
|||
nIconOffset = 0; |
|||
miCurrent = MENU_NEXTITEM(miCurrent); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// an initial side offset of 0 means the leftmost icon was changed
|
|||
// if we are scrolling to the right, decrement value for leftmost item
|
|||
if (direction == MENU_DIRECTION_RIGHT) |
|||
{ |
|||
if (nInitialSideOffset == 0) |
|||
{ |
|||
mi = MENU_PREVITEM(mi); |
|||
} |
|||
} |
|||
|
|||
// wait between the frames so that the animation can be seen
|
|||
WAIT(nWait); |
|||
// animation speed can be throtteled
|
|||
nWait += MENU_WAIT_INCREMENT; |
|||
} |
|||
} |
|||
|
|||
void menu_setpixel(int8_t x, int8_t y, int8_t isSet) |
|||
{ |
|||
uint8_t nColor; |
|||
|
|||
// mirror mirror on the wall, what's the quirkiest API of them all...
|
|||
x = NUM_COLS - 1 - x; |
|||
uint8_t nMiddle = (NUM_COLS - MENU_WIDTH_ICON) / 2; |
|||
|
|||
if (isSet != 0) |
|||
{ |
|||
if ((x >= nMiddle - MENU_WIDTH_DELIMITER) && (x < (nMiddle |
|||
+ MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER))) |
|||
{ |
|||
nColor = 3; |
|||
} |
|||
else if ((x == (nMiddle - MENU_WIDTH_DELIMITER - 1)) || (x == (nMiddle |
|||
+ MENU_WIDTH_ICON + MENU_WIDTH_DELIMITER))) |
|||
{ |
|||
nColor = 2; |
|||
} |
|||
else |
|||
{ |
|||
nColor = 1; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
nColor = 0; |
|||
} |
|||
|
|||
setpixel((pixel){x, y}, nColor); |
|||
} |
|||
|
@ -0,0 +1,34 @@ |
|||
/* A game chooser for borgs
|
|||
* by: Christian Kroll |
|||
* date: Tuesday, 2008/03/16 |
|||
*/ |
|||
|
|||
#ifndef MENU_H_ |
|||
#define MENU_H_ |
|||
|
|||
#include <inttypes.h> |
|||
|
|||
typedef enum menu_item_t |
|||
{ |
|||
MENU_ITEM_SNAKE, |
|||
MENU_ITEM_SPACEINVADERS, |
|||
MENU_ITEM_TETRIS, |
|||
MENU_ITEM_MAX // fake entry to mark the end
|
|||
} |
|||
menu_item_t; |
|||
|
|||
typedef enum menu_direction_t |
|||
{ |
|||
MENU_DIRECTION_LEFT, |
|||
MENU_DIRECTION_RIGHT, |
|||
MENU_DIRECTION_STILL |
|||
} |
|||
menu_direction_t; |
|||
|
|||
void menu(); |
|||
void menu_animate(menu_item_t currentItem, menu_direction_t direction); |
|||
uint8_t menu_getIconPixel(menu_item_t item, int8_t x, int8_t y); |
|||
void menu_setpixel(int8_t x, int8_t y, int8_t isSet); |
|||
|
|||
#endif /*MENU_H_*/ |
|||
|
@ -0,0 +1,127 @@ |
|||
#define PIXEL_C |
|||
|
|||
#include "config.h" |
|||
|
|||
#include "pixel.h" |
|||
#include "borg_hw/borg_hw.h" |
|||
|
|||
unsigned char shl_table[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; |
|||
|
|||
void clear_screen(unsigned char value){ |
|||
unsigned char p,*pix,v=0xff; |
|||
unsigned int i; |
|||
for(p=0;p<NUMPLANE;p++){ |
|||
pix=&pixmap[p][0][0]; |
|||
if(p==value) |
|||
v=0; |
|||
for(i=0;i<NUM_ROWS*LINEBYTES;i++) |
|||
pix[i]=v; |
|||
} |
|||
} |
|||
|
|||
void setpixel(pixel p, unsigned char value ){ |
|||
p.x %= NUM_COLS; |
|||
if(value>NUMPLANE) |
|||
value=NUMPLANE; |
|||
unsigned char pos = (p.y%NUM_ROWS)*LINEBYTES + (p.x/8); |
|||
unsigned char mask = shl_table[p.x%8]; |
|||
unsigned char plane; |
|||
for(plane=0;plane<value;plane++) |
|||
pixmap[plane][0][pos]|=mask; |
|||
mask ^=0xff; |
|||
for(;plane<NUMPLANE;plane++) |
|||
pixmap[plane][0][pos]&=mask; |
|||
} |
|||
|
|||
//shifts pixmap left. It is really shifted right, but because col0 is left in the Display it's left.
|
|||
void shift_pixmap_l(){ |
|||
unsigned char plane, row, byte; |
|||
|
|||
for(plane=0; plane<NUMPLANE; plane++){ |
|||
for(row=0;row<NUM_ROWS; row++){ |
|||
for(byte=0;byte<(LINEBYTES-1);byte++){ |
|||
pixmap[plane][row][byte] >>= 1; |
|||
pixmap[plane][row][byte] |= (pixmap[plane][row][byte+1] & 0x01) * 0x80;; |
|||
} |
|||
pixmap[plane][row][LINEBYTES-1] >>= 1; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
unsigned char get_pixel(pixel p){ |
|||
|
|||
if( (p.x >= NUM_COLS) || (p.y >= NUM_ROWS) ){ |
|||
return 0xff; |
|||
}else{ |
|||
return 0!= (pixmap[0][p.y][p.x/8] & shl_table[p.x%8]); |
|||
} |
|||
} |
|||
|
|||
|
|||
unsigned char get_next_pixel(pixel p, direction dir){ |
|||
pixel tmp; |
|||
switch (dir){ |
|||
case right: |
|||
tmp = (pixel){p.x-1, p.y}; |
|||
break; |
|||
case left: |
|||
tmp = (pixel){p.x+1, p.y}; |
|||
break; |
|||
case down: |
|||
tmp = (pixel){p.x, p.y+1}; |
|||
break; |
|||
case up: |
|||
tmp = (pixel){p.x, p.y-1}; |
|||
break; |
|||
default: |
|||
tmp = p; |
|||
break; |
|||
} |
|||
return get_pixel(tmp); |
|||
} |
|||
|
|||
direction direction_r(direction dir){ |
|||
switch (dir){ |
|||
case right: |
|||
return(down); |
|||
case down: |
|||
return(left); |
|||
case left: |
|||
return(up); |
|||
case up: |
|||
return (right); |
|||
} |
|||
return(0); |
|||
} |
|||
|
|||
void set_cursor(cursor* cur, pixel p){ |
|||
cur->pos = p; |
|||
switch (cur->mode){ |
|||
case clear: |
|||
clearpixel(p); |
|||
break; |
|||
case set: |
|||
setpixel(p,3); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
pixel next_pixel(pixel pix, direction dir){ |
|||
switch (dir){ |
|||
case right: |
|||
return((pixel){pix.x-1, pix.y}); |
|||
break; |
|||
case left: |
|||
return((pixel){pix.x+1, pix.y}); |
|||
break; |
|||
case down: |
|||
return((pixel){pix.x, pix.y+1}); |
|||
break; |
|||
case up: |
|||
return((pixel){pix.x, pix.y-1}); |
|||
break; |
|||
|
|||
} |
|||
return (pixel){0,0}; |
|||
} |
@ -0,0 +1,41 @@ |
|||
#ifndef PIXEL_H |
|||
#define PIXEL_H |
|||
|
|||
#define LINEBYTES (((NUM_COLS-1)/8)+1) |
|||
|
|||
extern unsigned char shl_table[]; |
|||
extern unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; |
|||
|
|||
typedef struct { |
|||
unsigned char x; |
|||
unsigned char y; |
|||
} pixel; |
|||
|
|||
|
|||
typedef enum {right,left,up,down} direction; |
|||
typedef struct { |
|||
pixel pos; |
|||
direction dir; |
|||
enum{clear=0, set=1} mode; |
|||
} cursor; |
|||
|
|||
/****************************************************************************
|
|||
* Pixel routines |
|||
*/ |
|||
void clear_screen(unsigned char value); |
|||
void setpixel(pixel p, unsigned char value); |
|||
#define clearpixel(p) setpixel(p, 0); |
|||
|
|||
unsigned char get_pixel(pixel p); |
|||
unsigned char get_next_pixel(pixel p, direction dir); |
|||
|
|||
pixel next_pixel(pixel pix, direction dir); |
|||
|
|||
direction direction_r(direction dir); |
|||
|
|||
void shift_pixmap_l(); |
|||
|
|||
|
|||
void set_cursor(cursor* cur, pixel p); |
|||
|
|||
#endif // PIXEL_H
|
@ -0,0 +1,68 @@ |
|||
/* memxor.S */ |
|||
/* |
|||
This file is part of the Crypto-avr-lib/microcrypt-lib. |
|||
Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de) |
|||
|
|||
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 3 of the License, or |
|||
(at your option) 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. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
/* |
|||
* File: memxor.S |
|||
* Author: Daniel Otte |
|||
* Date: 2008-08-07 |
|||
* License: GPLv3 or later |
|||
* Description: memxor, XORing one block into another |
|||
* |
|||
*/ |
|||
|
|||
/* |
|||
* void memxor(void* dest, const void* src, uint16_t n); |
|||
*/ |
|||
/* |
|||
* param dest is passed in r24:r25 |
|||
* param src is passed in r22:r23 |
|||
* param n is passed in r20:r21 |
|||
*/ |
|||
.global memxor |
|||
memxor: |
|||
movw r30, r24 |
|||
movw r26, r22 |
|||
movw r24, r20 |
|||
tst r24 |
|||
brne 1f |
|||
tst r25 |
|||
breq 2f |
|||
1: |
|||
ld r20, X+ |
|||
ld r21, Z |
|||
eor r20, r21 |
|||
st Z+, r20 |
|||
sbiw r24, 1 |
|||
brne 1b |
|||
2: |
|||
ret |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,7 @@ |
|||
#ifndef MEMXOR_H_ |
|||
#define MEMXOR_H_ |
|||
#include <stdint.h> |
|||
|
|||
void memxor(void* dest, const void* src, uint16_t n); |
|||
|
|||
#endif |
@ -0,0 +1,76 @@ |
|||
/* noekeon.h */ |
|||
/*
|
|||
This file is part of the Crypto-avr-lib/microcrypt-lib. |
|||
Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de) |
|||
|
|||
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 3 of the License, or |
|||
(at your option) 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. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
#ifndef NOEKEON_H_ |
|||
#define NOEKEON_H_ |
|||
|
|||
/**
|
|||
* \author Daniel Otte |
|||
* \email daniel.otte@rub.de |
|||
* \date 2008-04-11 |
|||
* \license GPLv3 |
|||
* \brief |
|||
* |
|||
* |
|||
*/ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
typedef uint8_t noekeon_ctx_t[16]; |
|||
|
|||
/** \fn void noekeon_enc(void* buffer, void* key)
|
|||
* \brief noekeon encrytion funtion |
|||
* |
|||
* This function encrypts a block (64 bit = 8 byte) with the noekeon encrytion |
|||
* algorithm. Due to the two modes of noekeon (direct mode and indirect mode) |
|||
* the second parameter either points directly to the key (direct mode) or to a |
|||
* context generated by the noekeon_init() function (indirect mode) |
|||
* \param buffer pointer to the 64 bit (8 byte) block to encrypt |
|||
* \param key pointer to either the key (128 bit = 16 byte; direct mode) or |
|||
* to the context (indirect mode) |
|||
*/ |
|||
void noekeon_enc(void* buffer, const void* key); |
|||
|
|||
/** \fn void noekeon_enc(void* buffer, void* key)
|
|||
* \brief noekeon encrytion funtion |
|||
* |
|||
* This function decrypts a block (64 bit = 8 byte) encrypted with the noekeon |
|||
* encrytion algorithm. Due to the two modes of noekeon (direct mode and |
|||
* indirect mode) the second parameter either points directly to the key |
|||
* (direct mode) or to a context generated by the noekeon_init() function |
|||
* (indirect mode) |
|||
* \param buffer pointer to the 64 bit (8 byte) block to decrypt |
|||
* \param key pointer to either the key (128 bit = 16 byte; direct mode) or |
|||
* to the context (indirect mode) |
|||
*/ |
|||
void noekeon_dec(void* buffer, const void* key); |
|||
|
|||
|
|||
/** \fn void noekeon_init(void* key, noekeon_ctx_t* ctx)
|
|||
* \brief noekeon context generation function for indirect mode |
|||
* |
|||
* This function generates a context from the supplied key for using |
|||
* noekeon in indirect mode. For using noekeon in direct mode supply the key |
|||
* direct to the noekeon_enc() and noekeon_dec() functions |
|||
* \param key pointer to the key (128 bit = 16 byte) |
|||
* \param ctx pointer to the context to fill with key material |
|||
* to the context (indirect mode) |
|||
*/ |
|||
void noekeon_init(const void* key, noekeon_ctx_t* ctx); |
|||
|
|||
#endif /*NOEKEON_H_*/ |
@ -0,0 +1,641 @@ |
|||
/* noekeon_asm.S */ |
|||
/* |
|||
This file is part of the Crypto-avr-lib/microcrypt-lib. |
|||
Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de) |
|||
|
|||
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 3 of the License, or |
|||
(at your option) 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. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
/* |
|||
* noekeon assembler implementation for avr |
|||
* author: Daniel Otte |
|||
* email: daniel.otte@rub.de |
|||
* license: GPLv3 |
|||
*/ |
|||
|
|||
#include <avr/io.h> |
|||
|
|||
.macro push_all |
|||
push r2 |
|||
push r3 |
|||
push r4 |
|||
push r5 |
|||
push r6 |
|||
push r7 |
|||
push r8 |
|||
push r9 |
|||
push r10 |
|||
push r11 |
|||
push r12 |
|||
push r13 |
|||
push r14 |
|||
push r15 |
|||
push r16 |
|||
push r17 |
|||
push r28 |
|||
push r29 |
|||
.endm |
|||
|
|||
.macro pop_all |
|||
pop r29 |
|||
pop r28 |
|||
pop r17 |
|||
pop r16 |
|||
pop r15 |
|||
pop r14 |
|||
pop r13 |
|||
pop r12 |
|||
pop r11 |
|||
pop r10 |
|||
pop r9 |
|||
pop r8 |
|||
pop r7 |
|||
pop r6 |
|||
pop r5 |
|||
pop r4 |
|||
pop r3 |
|||
pop r2 |
|||
clr r1 |
|||
.endm |
|||
|
|||
push_all_func: |
|||
pop r31 |
|||
pop r30 |
|||
push_all |
|||
ijmp |
|||
|
|||
pop_all_func: |
|||
pop r31 |
|||
pop r30 |
|||
pop_all |
|||
ijmp |
|||
|
|||
.macro xchg a b |
|||
eor \a, \b |
|||
eor \b, \a |
|||
eor \a, \b |
|||
.endm |
|||
|
|||
.macro op32 op a b |
|||
\op \a\()_0, \b\()_0 |
|||
\op \a\()_1, \b\()_1 |
|||
\op \a\()_2, \b\()_2 |
|||
\op \a\()_3, \b\()_3 |
|||
.endm |
|||
|
|||
|
|||
.macro op32_4t op a b c d w x y z |
|||
\op \a, \w |
|||
\op \b, \x |
|||
\op \c, \y |
|||
\op \d, \z |
|||
.endm |
|||
|
|||
|
|||
.macro op32_prefix op p q a b c d w x y z |
|||
\op \p\()\a, \q\()\w |
|||
\op \p\()\b, \q\()\x |
|||
\op \p\()\c, \q\()\y |
|||
\op \p\()\d, \q\()\z |
|||
.endm |
|||
|
|||
; === bigendian_rotl32 === |
|||
; this function rotates a 32bit bigendian word n bits to the left |
|||
; param1: the 32-bit value |
|||
; given in r25,r24,r23,r22 (r22 is most significant) |
|||
; param2: the 8-bit parameter giving the number of bits to rotate |
|||
; given in r20 |
|||
; return: the rotatet 32-bit word |
|||
; given in r25,r24,r23,r22 |
|||
|
|||
bigendian_rotl32: |
|||
/* copy high bit of r22 to carry */ |
|||
mov r1, r22 |
|||
2: |
|||
rol r1 |
|||
|
|||
rol r25 |
|||
rol r24 |
|||
rol r23 |
|||
rol r22 |
|||
|
|||
dec r20 |
|||
brne 2b |
|||
bigendian_rotl32_exit: |
|||
clr r1 |
|||
ret |
|||
|
|||
|
|||
/******************************************************************************/ |
|||
|
|||
; === bigendian_rotl32 === |
|||
; this function rotates a 32bit bigendian word n bits to the right |
|||
; param1: the 32-bit value |
|||
; given in r25,r24,r23,r22 (r22 is most significant) |
|||
; param2: the 8-bit parameter giving the number of bits to rotate |
|||
; given in r20 |
|||
; return: the rotatet 32-bit word |
|||
; given in r25,r24,r23,r22 |
|||
|
|||
bigendian_rotr32: |
|||
/* copy high bit of r25 to carry */ |
|||
|
|||
mov r1, r25 |
|||
2: |
|||
ror r1 |
|||
|
|||
ror r22 |
|||
ror r23 |
|||
ror r24 |
|||
ror r25 |
|||
dec r20 |
|||
brne 2b |
|||
bigendian_rotr32_exit: |
|||
clr r1 |
|||
ret |
|||
|
|||
/******************************************************************************/ |
|||
/* |
|||
void theta(uint32_t* k, uint32_t* a){ |
|||
uint32_t temp; |
|||
temp = a[0] ^ a[2]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8); |
|||
a[1] ^= temp; |
|||
a[3] ^= temp; |
|||
|
|||
a[0] ^= k[0]; |
|||
a[1] ^= k[1]; |
|||
a[2] ^= k[2]; |
|||
a[3] ^= k[3]; |
|||
|
|||
temp = a[1] ^ a[3]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8); |
|||
a[0] ^= temp; |
|||
a[2] ^= temp; |
|||
} |
|||
*/ |
|||
|
|||
round_const: .byte 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A, \ |
|||
0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A, \ |
|||
0xD4 |
|||
|
|||
;-- a[0] |
|||
state0_0 = 2 |
|||
state0_1 = 3 |
|||
state0_2 = 4 |
|||
state0_3 = 5 |
|||
;-- a[1] |
|||
state1_0 = 6 |
|||
state1_1 = 7 |
|||
state1_2 = 8 |
|||
state1_3 = 9 |
|||
;-- a[2] |
|||
state2_0 = 10 |
|||
state2_1 = 11 |
|||
state2_2 = 12 |
|||
state2_3 = 13 |
|||
;-- a[3] |
|||
state3_0 = 14 |
|||
state3_1 = 15 |
|||
state3_2 = 16 |
|||
state3_3 = 17 |
|||
|
|||
; === theta === |
|||
; |
|||
; param1: the state in r2-r17 |
|||
; param2: pointer to k in X (r26,r27) |
|||
; |
|||
temp_a = 18 |
|||
temp_b = 19 |
|||
temp_c = 20 |
|||
temp_d = 21 |
|||
|
|||
theta: |
|||
/* temp = a[0] ^ a[2]; temp ^= temp>>>8 ^ temp<<<8 */ |
|||
op32_prefix mov, temp_, state0_, a,b,c,d, 0,1,2,3 |
|||
op32_prefix eor, temp_, state2_, a,b,c,d, 0,1,2,3 |
|||
|
|||
mov r1, temp_a |
|||
eor r1, temp_b |
|||
eor r1, temp_c |
|||
eor r1, temp_d |
|||
|
|||
op32_prefix eor, temp_, r, a,b,c,d, 1,1,1,1 |
|||
|
|||
/* temp is know a little bit mixed c,d,a,b (if abcd is normal order) */ |
|||
/* a[1] ^= temp */ |
|||
eor state1_0, temp_c |
|||
eor state1_1, temp_d |
|||
eor state1_2, temp_a |
|||
eor state1_3, temp_b |
|||
/* a[3] ^= temp */ |
|||
eor state3_0, temp_c |
|||
eor state3_1, temp_d |
|||
eor state3_2, temp_a |
|||
eor state3_3, temp_b |
|||
|
|||
/* state ^ k (X points to K) */ |
|||
ldi r28, 2 |
|||
clr r29 /* Y points to r2 aka state0_0 */ |
|||
ldi temp_a, 16 |
|||
1: |
|||
ld r1, X+ |
|||
ld r0, Y |
|||
eor r1, r0 |
|||
st Y+, r1 |
|||
dec temp_a |
|||
brne 1b |
|||
sbiw r26, 16 /* set X back to key */ |
|||
|
|||
mov temp_a, state1_0 |
|||
mov temp_b, state1_1 |
|||
mov temp_c, state1_2 |
|||
mov temp_d, state1_3 |
|||
eor temp_a, state3_0 |
|||
eor temp_b, state3_1 |
|||
eor temp_c, state3_2 |
|||
eor temp_d, state3_3 |
|||
mov r1, temp_a |
|||
eor r1, temp_b |
|||
eor r1, temp_c |
|||
eor r1, temp_d |
|||
eor temp_a, r1 |
|||
eor temp_b, r1 |
|||
eor temp_c, r1 |
|||
eor temp_d, r1 |
|||
/* temp is know a little bit mixed c,d,a,b (if abcd is normal order) */ |
|||
/* a[0] ^= temp */ |
|||
eor state0_0, temp_c |
|||
eor state0_1, temp_d |
|||
eor state0_2, temp_a |
|||
eor state0_3, temp_b |
|||
/* a[2] ^= temp */ |
|||
eor state2_0, temp_c |
|||
eor state2_1, temp_d |
|||
eor state2_2, temp_a |
|||
eor state2_3, temp_b |
|||
|
|||
clr r1 |
|||
ret |
|||
|
|||
/******************************************************************************/ |
|||
#ifndef NOEKEON_NO_ENC |
|||
; === noekeon_enc === |
|||
; |
|||
; param1: pointer to buffer (r24,r25) |
|||
; param2: pointer to k (r22,r23) |
|||
; |
|||
.global noekeon_enc |
|||
noekeon_enc: |
|||
rcall push_all_func |
|||
/* load state */ |
|||
movw r26, r22 |
|||
ldi r28, 2 |
|||
clr r29 /* Y points at r2 aka state0_0 */ |
|||
movw r30, r24 /* Z points at state */ |
|||
push r30 |
|||
push r31 |
|||
ldi r22, 16 |
|||
push r22 /* 16 is also the number of rounds and gets pushed here */ |
|||
1: |
|||
ld r0, Z+ |
|||
st Y+, r0 |
|||
dec r22 |
|||
brne 1b |
|||
/* state loaded */ |
|||
push r1 /* push round constan2 (0x00) */ |
|||
ldi r20, 0x80 |
|||
push r20 /* push round constan2 (0x00) */ |
|||
rjmp 3f |
|||
2: |
|||
ldi r30, lo8(round_const+15) |
|||
ldi r31, hi8(round_const+15) |
|||
sub r30, r22 |
|||
sbci r31, 0 |
|||
clr r1 |
|||
push r1 |
|||
lpm r0, Z |
|||
push r0 |
|||
3: |
|||
rcall round /* pops rc2 & rc1 */ |
|||
pop r22 |
|||
dec r22 |
|||
push r22 |
|||
brne 2b |
|||
|
|||
pop r22 |
|||
|
|||
ldi r22, 0xD4 |
|||
eor state0_3, r22 |
|||
rcall theta |
|||
|
|||
pop r31 |
|||
pop r30 |
|||
clr r29 |
|||
ldi r28, 2 |
|||
ldi r22, 16 |
|||
1: |
|||
ld r0, Y+ |
|||
st Z+, r0 |
|||
dec r22 |
|||
brne 1b |
|||
|
|||
rcall pop_all_func |
|||
ret |
|||
#endif |
|||
/******************************************************************************/ |
|||
/******************************************************************************/ |
|||
#ifndef NOEKEON_NO_DEC |
|||
|
|||
; === noekeon_dec === |
|||
; |
|||
; param1: pointer to buffer/state (r24,r25) |
|||
; param2: pointer to k (r22,r23) |
|||
; |
|||
.global noekeon_dec |
|||
noekeon_dec: |
|||
rcall push_all_func |
|||
/* allocate 16 bytes on the stack */ |
|||
in r30, _SFR_IO_ADDR(SPL) |
|||
in r31, _SFR_IO_ADDR(SPH) |
|||
sbiw r30, 16 |
|||
out _SFR_IO_ADDR(SPH), r31 |
|||
out _SFR_IO_ADDR(SPL), r30 |
|||
|
|||
adiw r30, 1 |
|||
/* push state pointer */ |
|||
push r24 |
|||
push r25 |
|||
movw r26, r22 /* move key ptr to X */ |
|||
|
|||
/* set stackkey to zero */ |
|||
ldi r22, 16 |
|||
1: st Z+, r1 |
|||
dec r22 |
|||
brne 1b |
|||
|
|||
/* copy key to state */ |
|||
clr r29 |
|||
ldi r28, 2 |
|||
ldi r22, 16 |
|||
1: ld r0, X+ |
|||
st Y+, r0 |
|||
dec r22 |
|||
brne 1b |
|||
|
|||
movw r26, r30 |
|||
sbiw r26, 16 /* set X back to begining of stack key */ |
|||
rcall theta |
|||
|
|||
/* mov state to stackkey */ |
|||
clr r29 |
|||
ldi r28, 2 |
|||
ldi r22, 16 |
|||
1: ld r0, Y+ |
|||
st X+, r0 |
|||
dec r22 |
|||
brne 1b |
|||
sbiw r26, 16 /* set X back to begining of stack key */ |
|||
|
|||
/* move data from stateptr to state */ |
|||
pop r31 |
|||
pop r30 |
|||
push r30 |
|||
push r31 |
|||
clr r29 |
|||
ldi r28, 2 |
|||
ldi r22, 16 |
|||
push r22 |
|||
1: ld r0, Z+ |
|||
st Y+, r0 |
|||
dec r22 |
|||
brne 1b |
|||
|
|||
;--- snip 8< ---- |
|||
|
|||
ldi r20, 0xD4 |
|||
push r20 /* push round constant2 (0xD4) */ |
|||
push r22 /* push round constan1 (0x00) */ |
|||
rjmp 3f |
|||
2: |
|||
ldi r30, lo8(round_const-1) |
|||
ldi r31, hi8(round_const-1) |
|||
clr r1 |
|||
add r30, r22 |
|||
adc r31, r1 |
|||
lpm r0, Z |
|||
push r0 |
|||
push r1 |
|||
3: |
|||
rcall round /* pops rc2 & rc1 */ |
|||
pop r22 |
|||
dec r22 |
|||
push r22 |
|||
brne 2b |
|||
;---- |
|||
pop r22 |
|||
|
|||
rcall theta |
|||
ldi r22, 0x80 |
|||
eor state0_3, r22 |
|||
|
|||
write_state_back: |
|||
/* write state back */ |
|||
pop r31 /* pop state pointer */ |
|||
pop r30 |
|||
clr r29 |
|||
ldi r28, 2 |
|||
ldi r22, 16 |
|||
1: |
|||
ld r0, Y+ |
|||
st Z+, r0 |
|||
dec r22 |
|||
brne 1b |
|||
|
|||
/* remove key from stack */ |
|||
in r30, _SFR_IO_ADDR(SPL) |
|||
in r31, _SFR_IO_ADDR(SPH) |
|||
adiw r30, 16 |
|||
out _SFR_IO_ADDR(SPH), r31 |
|||
out _SFR_IO_ADDR(SPL), r30 |
|||
rcall pop_all_func |
|||
ret |
|||
#endif |
|||
/******************************************************************************/ |
|||
|
|||
|
|||
round: |
|||
pop r24 |
|||
pop r25 |
|||
pop r1 |
|||
eor state0_3, r1 |
|||
rcall theta |
|||
pop r1 |
|||
eor state0_3, r1 |
|||
push r25 |
|||
push r24 |
|||
pi_gamma_pi: |
|||
ldi r30, pm_lo8(bigendian_rotl32) |
|||
ldi r31, pm_hi8(bigendian_rotl32) |
|||
rcall pi |
|||
/* pi1 done; now gamma */ |
|||
rcall gamma_1 |
|||
/* a[0] <-> a[3] */ |
|||
xchg state0_0, state3_0 |
|||
xchg state0_1, state3_1 |
|||
xchg state0_2, state3_2 |
|||
xchg state0_3, state3_3 |
|||
/* a[2] ^= a[0] ^ a[1] ^ a[3] */ |
|||
op32 eor, state2, state0 |
|||
op32 eor, state2, state1 |
|||
op32 eor, state2, state3 |
|||
|
|||
rcall gamma_1 |
|||
ldi r30, pm_lo8(bigendian_rotr32) |
|||
ldi r31, pm_hi8(bigendian_rotr32) |
|||
rcall pi |
|||
ret |
|||
|
|||
gamma_1: |
|||
/* a[1] ^= ~(a[3]|a[2])*/ |
|||
mov r1, state3_0 |
|||
or r1, state2_0 |
|||
com r1 |
|||
eor state1_0, r1 |
|||
|
|||
mov r1, state3_1 |
|||
or r1, state2_1 |
|||
com r1 |
|||
eor state1_1, r1 |
|||
|
|||
mov r1, state3_2 |
|||
or r1, state2_2 |
|||
com r1 |
|||
eor state1_2, r1 |
|||
|
|||
mov r1, state3_3 |
|||
or r1, state2_3 |
|||
com r1 |
|||
eor state1_3, r1 |
|||
|
|||
/* a[0] ^= a[2]&a[1] */ |
|||
mov r1, state2_0 |
|||
and r1, state1_0 |
|||
eor state0_0, r1 |
|||
|
|||
mov r1, state2_1 |
|||
and r1, state1_1 |
|||
eor state0_1, r1 |
|||
|
|||
mov r1, state2_2 |
|||
and r1, state1_2 |
|||
eor state0_2, r1 |
|||
|
|||
mov r1, state2_3 |
|||
and r1, state1_3 |
|||
eor state0_3, r1 |
|||
ret |
|||
|
|||
pi: |
|||
/* a[1] <<<= 1*/ |
|||
mov r22, state1_0 |
|||
mov r23, state1_1 |
|||
mov r24, state1_2 |
|||
mov r25, state1_3 |
|||
ldi r20, 1 |
|||
icall |
|||
mov state1_0, r22 |
|||
mov state1_1, r23 |
|||
mov state1_2, r24 |
|||
mov state1_3, r25 |
|||
/* a[2] <<<= 5*/ |
|||
mov r22, state2_0 |
|||
mov r23, state2_1 |
|||
mov r24, state2_2 |
|||
mov r25, state2_3 |
|||
ldi r20, 5 |
|||
icall |
|||
mov state2_0, r22 |
|||
mov state2_1, r23 |
|||
mov state2_2, r24 |
|||
mov state2_3, r25 |
|||
/* a[3] <<<= 2*/ |
|||
mov r22, state3_0 |
|||
mov r23, state3_1 |
|||
mov r24, state3_2 |
|||
mov r25, state3_3 |
|||
ldi r20, 2 |
|||
icall |
|||
mov state3_0, r22 |
|||
mov state3_1, r23 |
|||
mov state3_2, r24 |
|||
mov state3_3, r25 |
|||
ret |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
/* |
|||
void noekeon_init(void* key, noekeon_ctx_t* ctx){ |
|||
uint8_t nullv[16]; |
|||
|
|||
memset(nullv, 0, 16); |
|||
memcpy(ctx, key, 16); |
|||
noekeon_enc(ctx, nullv); |
|||
} |
|||
*/ |
|||
|
|||
#ifndef NOEKEON_NO_INIT |
|||
|
|||
.global noekeon_init |
|||
noekeon_init: |
|||
; === noekeon_init === |
|||
; |
|||
; param1: pointer to key (r24,r25) |
|||
; param2: pointer to context (r22,r23) |
|||
; |
|||
in r30, _SFR_IO_ADDR(SPL) |
|||
in r31, _SFR_IO_ADDR(SPH) |
|||
sbiw r30, 16 |
|||
out _SFR_IO_ADDR(SPH), r31 |
|||
out _SFR_IO_ADDR(SPL), r30 |
|||
|
|||
movw r26, r22 |
|||
adiw r30, 1 |
|||
movw r22, r30 |
|||
/* set nullv(stack) to zero */ |
|||
ldi r20, 16 |
|||
1: st Z+, r1 |
|||
dec r20 |
|||
brne 1b |
|||
|
|||
/* copy key data to ctx */ |
|||
movw r30, r24 |
|||
ldi r20, 16 |
|||
1: ld r1, Z+ |
|||
st X+, r1 |
|||
dec r20 |
|||
brne 1b |
|||
clr r1 |
|||
|
|||
sbiw r26, 16 |
|||
movw r24, r26 |
|||
rcall noekeon_enc |
|||
|
|||
in r30, _SFR_IO_ADDR(SPL) |
|||
in r31, _SFR_IO_ADDR(SPH) |
|||
adiw r30, 16 |
|||
out _SFR_IO_ADDR(SPH), r31 |
|||
out _SFR_IO_ADDR(SPL), r30 |
|||
ret |
|||
|
|||
#endif |
|||
|
|||
|
@ -0,0 +1,111 @@ |
|||
/**
|
|||
* \file persistentCounter.c |
|||
* \author Daniel Otte |
|||
* \brief a persistent 24-bit counter in EEPROM for ATmega µC |
|||
* |
|||
*/ |
|||
|
|||
#include <stdint.h> |
|||
#include <avr/interrupt.h> /* cli() & sei() */ |
|||
#include <avr/eeprom.h> |
|||
#include "../config.h" |
|||
|
|||
#ifdef ERROR_HANDLING |
|||
#include "error-handling.h" |
|||
#define PERSISTENT_COUNTER_OVERFLOW (void*)0, 2,4,1 |
|||
#define PERSISTENT_COUNTER_WRITER_ERROR (void*)0, 2,4,2 |
|||
#endif |
|||
|
|||
#define RING_SIZE 168 |
|||
|
|||
uint8_t ring_idx = 0xff; |
|||
|
|||
uint16_t EEMEM B08_23; |
|||
uint8_t EEMEM B0_7[RING_SIZE]; |
|||
|
|||
#ifdef INIT_EEPROM |
|||
void init_buffer(void){ |
|||
uint8_t i; |
|||
eeprom_busy_wait(); |
|||
eeprom_write_word(&B08_23, 0x0000); |
|||
for(i=0; i<RING_SIZE; ++i){ |
|||
eeprom_busy_wait(); |
|||
eeprom_write_byte(&(B0_7[i]), 0x00); |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
void percnt_init(void){ |
|||
uint8_t i; |
|||
uint8_t maxidx=0; |
|||
uint8_t t,max=eeprom_read_byte(&(B0_7[0])); |
|||
#ifdef INIT_EEPROM |
|||
if (eeprom_read_word(&B08_23)==0xFFFF){ /* test if the 2 MSB == 0xFFFF*/ |
|||
if (eeprom_read_word((uint16_t*)&(B0_7[0]))==0xFFFF) /* test the first to bytes of ringbuffer*/ |
|||
init_buffer(); |
|||
} |
|||
#endif |
|||
for(i=0; i<RING_SIZE; ++i){ /* this might be speed up, but such optimisation could lead to timing attacks */ |
|||
eeprom_busy_wait(); |
|||
t=eeprom_read_byte(&(B0_7[i])); |
|||
if(t==max+1){ |
|||
max=t; |
|||
maxidx=i; |
|||
} |
|||
} |
|||
ring_idx = (maxidx==RING_SIZE)?0:maxidx; |
|||
} |
|||
|
|||
uint32_t percnt_get(void){ |
|||
uint32_t ret=0; |
|||
|
|||
if(ring_idx==0xff) |
|||
percnt_init(); |
|||
cli(); |
|||
eeprom_busy_wait(); |
|||
ret=eeprom_read_word(&B08_23)<<8; |
|||
eeprom_busy_wait(); |
|||
ret |= eeprom_read_byte(&(B0_7[ring_idx])); |
|||
sei(); |
|||
return ret; |
|||
} |
|||
|
|||
void percnt_inc(void){ |
|||
/* we must make this resistant agaist power off while this is running ... */ |
|||
uint32_t u; |
|||
|
|||
if(ring_idx==0xff) |
|||
percnt_init(); |
|||
|
|||
u = percnt_get(); |
|||
cli(); |
|||
/* it's important to write msb first! */ |
|||
if((u&0x000000ff) == 0xff){ |
|||
if((u&0x0000ffff) == 0xffff){ |
|||
if((u&0x00ffffff) == 0xffffff){ |
|||
/* we can turn the lights off now. it's time to die */ |
|||
#ifdef ERROR_HANDLING |
|||
error(PERSISTENT_COUNTER_OVERFLOW); |
|||
#endif |
|||
} |
|||
eeprom_busy_wait(); |
|||
eeprom_write_byte(&(((uint8_t*)&B08_23)[1]),((u+1)>>16)&0xff); |
|||
} |
|||
eeprom_busy_wait(); |
|||
eeprom_write_byte(&(((uint8_t*)&B08_23)[0]),((u+1)>>8)&0xff); |
|||
} |
|||
/* set least significant byte (in ringbuffer) */ |
|||
ring_idx = (ring_idx+1)%RING_SIZE; |
|||
eeprom_busy_wait(); |
|||
eeprom_write_byte(&(B0_7[ring_idx]),(u+1)&0xff); |
|||
eeprom_busy_wait(); |
|||
|
|||
if(u+1 != percnt_get()){ |
|||
#ifdef ERROR_HANDLING |
|||
error(PERSISTENT_COUNTER_WRITER_ERROR); |
|||
#endif |
|||
} |
|||
|
|||
sei(); |
|||
} |
|||
|
@ -0,0 +1,23 @@ |
|||
/**
|
|||
* \file persistentCounter.h |
|||
* \author Daniel Otte |
|||
* \brief a persistent 24-bit vounter in EEPROM for ATmega µC |
|||
* |
|||
* |
|||
*/ |
|||
|
|||
#ifndef PERSISTENTCOUNTER_H_ |
|||
#define PERSISTENTCOUNTER_H_ |
|||
|
|||
|
|||
#include <stdint.h> |
|||
|
|||
#define PERSISTENT_COUNTER_BITS 24 |
|||
|
|||
void percnt_init(void); |
|||
uint32_t percnt_get(void); |
|||
void percnt_inc(void); |
|||
|
|||
|
|||
|
|||
#endif /*PERSISTENTCOUNTER_H_*/ |
@ -0,0 +1,49 @@ |
|||
/**
|
|||
* \author Daniel Otte |
|||
* \date 2008-08-24 |
|||
* \license GPLv3 or later |
|||
* \brief random number generator based on noekeon running in CFB-mode |
|||
* |
|||
*/ |
|||
|
|||
#include "noekeon.h" |
|||
#include "memxor.h" |
|||
#include <stdint.h> |
|||
#include <string.h> |
|||
|
|||
uint8_t random_state[16]; |
|||
uint8_t random_key[16]; |
|||
|
|||
|
|||
uint8_t random8(void){ |
|||
static uint8_t sr[16]; |
|||
static uint8_t i=0; |
|||
|
|||
if(i==0){ |
|||
noekeon_enc(random_state, random_key); |
|||
memcpy(sr, random_state, 16); |
|||
i=15; |
|||
return sr[15]; |
|||
} |
|||
--i; |
|||
return sr[i]; |
|||
} |
|||
|
|||
void random_block(void* dest){ |
|||
noekeon_enc(random_state, random_key); |
|||
memcpy(dest, random_state, 16); |
|||
} |
|||
|
|||
void srandom32(uint32_t seed){ |
|||
memcpy(random_key, &seed, 4); |
|||
} |
|||
|
|||
void random_seed(const void* buffer){ |
|||
memcpy(random_key, buffer, 16); |
|||
} |
|||
|
|||
void random_add(const void* buffer){ |
|||
memxor(random_key, buffer, 16); |
|||
} |
|||
|
|||
|
@ -0,0 +1,22 @@ |
|||
/**
|
|||
* \author Daniel Otte |
|||
* \date 2008-08-24 |
|||
* \license GPLv3 or later |
|||
* \brief random number generator based on noekeon running in CFB-mode |
|||
* |
|||
*/ |
|||
|
|||
#ifndef PRNG_H_ |
|||
#define PRNG_H_ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
uint8_t random8(void); |
|||
void random_block(void* dest); |
|||
void srandom32(uint32_t seed); |
|||
void random_seed(const void* buffer); |
|||
void random_add(const void* buffer); |
|||
|
|||
#endif /* PRNG_H_*/ |
|||
|
|||
|
@ -0,0 +1,21 @@ |
|||
|
|||
OBJECTS += $(patsubst %.c,%.o,${SRC}) |
|||
OBJECTS += $(patsubst %.S,%.o,${ASRC}) |
|||
|
|||
%.a: $(OBJECTS) |
|||
$(RM) $@ |
|||
$(AR) qcv $@ $^ |
|||
# $(STRIP) --strip-unneeded $@
|
|||
|
|||
%.o: %.S |
|||
$(CC) -o $@ $(CPPFLAGS) $(ASFLAGS) -c $< |
|||
|
|||
clean-common: |
|||
$(RM) $(TARGET) *.[odasE] *.d.new *~ |
|||
|
|||
clean: clean-common |
|||
|
|||
all: |
|||
make -C $(TOPDIR) all |
|||
|
|||
include $(TOPDIR)/depend.mk |
File diff suppressed because it is too large
@ -0,0 +1,4 @@ |
|||
This is NOT the official version of dialog. This version has been |
|||
significantly modified from the original. It is for use by the Linux |
|||
kernel configuration script. Please do not bother Savio Lam with |
|||
questions about this program. |
@ -0,0 +1,46 @@ |
|||
HOSTCFLAGS += -DLOCALE |
|||
LIBS = -lncurses |
|||
|
|||
ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h)) |
|||
HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>" |
|||
else |
|||
ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h)) |
|||
HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>" |
|||
else |
|||
ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h)) |
|||
HOSTCFLAGS += -DCURSES_LOC="<ncurses.h>" |
|||
else |
|||
HOSTCFLAGS += -DCURSES_LOC="<curses.h>" |
|||
endif |
|||
endif |
|||
endif |
|||
|
|||
|
|||
OBJS = checklist.o menubox.o textbox.o yesno.o inputbox.o \
|
|||
util.o lxdialog.o msgbox.o |
|||
|
|||
%.o: %.c |
|||
$(HOSTCC) $(HOSTCFLAGS) -c -o $@ $< |
|||
|
|||
all: ncurses lxdialog |
|||
|
|||
lxdialog: $(OBJS) |
|||
$(HOSTCC) -o lxdialog $(OBJS) $(LIBS) |
|||
|
|||
ncurses: |
|||
@echo "main() {}" > lxtemp.c |
|||
@if $(HOSTCC) -lncurses lxtemp.c ; then \
|
|||
rm -f lxtemp.c a.out; \
|
|||
else \
|
|||
rm -f lxtemp.c; \
|
|||
echo -e "\007" ;\
|
|||
echo ">> Unable to find the Ncurses libraries." ;\
|
|||
echo ">>" ;\
|
|||
echo ">> You must have Ncurses installed in order" ;\
|
|||
echo ">> to use 'make menuconfig'" ;\
|
|||
echo ;\
|
|||
exit 1 ;\
|
|||
fi |
|||
|
|||
clean: |
|||
rm -f core *.o *~ lxdialog |
@ -0,0 +1,369 @@ |
|||
/*
|
|||
* checklist.c -- implements the checklist box |
|||
* |
|||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |
|||
* Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension |
|||
* Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two |
|||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) |
|||
* |
|||
* 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 (at your option) 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. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|||
*/ |
|||
|
|||
#include "dialog.h" |
|||
|
|||
static int list_width, check_x, item_x, checkflag; |
|||
|
|||
/*
|
|||
* Print list item |
|||
*/ |
|||
static void |
|||
print_item (WINDOW * win, const char *item, int status, |
|||
int choice, int selected) |
|||
{ |
|||
int i; |
|||
|
|||
/* Clear 'residue' of last item */ |
|||
wattrset (win, menubox_attr); |
|||
wmove (win, choice, 0); |
|||
for (i = 0; i < list_width; i++) |
|||
waddch (win, ' '); |
|||
|
|||
wmove (win, choice, check_x); |
|||
wattrset (win, selected ? check_selected_attr : check_attr); |
|||
if (checkflag == FLAG_CHECK) |
|||
wprintw (win, "[%c]", status ? 'X' : ' '); |
|||
else |
|||
wprintw (win, "(%c)", status ? 'X' : ' '); |
|||
|
|||
wattrset (win, selected ? tag_selected_attr : tag_attr); |
|||
mvwaddch(win, choice, item_x, item[0]); |
|||
wattrset (win, selected ? item_selected_attr : item_attr); |
|||
waddstr (win, (char *)item+1); |
|||
if (selected) { |
|||
wmove (win, choice, check_x+1); |
|||
wrefresh (win); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Print the scroll indicators. |
|||
*/ |
|||
static void |
|||
print_arrows (WINDOW * win, int choice, int item_no, int scroll, |
|||
int y, int x, int height) |
|||
{ |
|||
wmove(win, y, x); |
|||
|
|||
if (scroll > 0) { |
|||
wattrset (win, uarrow_attr); |
|||
waddch (win, ACS_UARROW); |
|||
waddstr (win, "(-)"); |
|||
} |
|||
else { |
|||
wattrset (win, menubox_attr); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
} |
|||
|
|||
y = y + height + 1; |
|||
wmove(win, y, x); |
|||
|
|||
if ((height < item_no) && (scroll + choice < item_no - 1)) { |
|||
wattrset (win, darrow_attr); |
|||
waddch (win, ACS_DARROW); |
|||
waddstr (win, "(+)"); |
|||
} |
|||
else { |
|||
wattrset (win, menubox_border_attr); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Display the termination buttons |
|||
*/ |
|||
static void |
|||
print_buttons( WINDOW *dialog, int height, int width, int selected) |
|||
{ |
|||
int x = width / 2 - 11; |
|||
int y = height - 2; |
|||
|
|||
print_button (dialog, "Select", y, x, selected == 0); |
|||
print_button (dialog, " Help ", y, x + 14, selected == 1); |
|||
|
|||
wmove(dialog, y, x+1 + 14*selected); |
|||
wrefresh (dialog); |
|||
} |
|||
|
|||
/*
|
|||
* Display a dialog box with a list of options that can be turned on or off |
|||
* The `flag' parameter is used to select between radiolist and checklist. |
|||
*/ |
|||
int |
|||
dialog_checklist (const char *title, const char *prompt, int height, int width, |
|||
int list_height, int item_no, const char * const * items, int flag) |
|||
|
|||
{ |
|||
int i, x, y, box_x, box_y; |
|||
int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; |
|||
WINDOW *dialog, *list; |
|||
|
|||
checkflag = flag; |
|||
|
|||
/* Allocate space for storing item on/off status */ |
|||
if ((status = malloc (sizeof (int) * item_no)) == NULL) { |
|||
endwin (); |
|||
fprintf (stderr, |
|||
"\nCan't allocate memory in dialog_checklist().\n"); |
|||
exit (-1); |
|||
} |
|||
|
|||
/* Initializes status */ |
|||
for (i = 0; i < item_no; i++) { |
|||
status[i] = !strcasecmp (items[i * 3 + 2], "on"); |
|||
if (!choice && status[i]) |
|||
choice = i; |
|||
} |
|||
|
|||
max_choice = MIN (list_height, item_no); |
|||
|
|||
/* center dialog box on screen */ |
|||
x = (COLS - width) / 2; |
|||
y = (LINES - height) / 2; |
|||
|
|||
draw_shadow (stdscr, y, x, height, width); |
|||
|
|||
dialog = newwin (height, width, y, x); |
|||
keypad (dialog, TRUE); |
|||
|
|||
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); |
|||
wattrset (dialog, border_attr); |
|||
mvwaddch (dialog, height-3, 0, ACS_LTEE); |
|||
for (i = 0; i < width - 2; i++) |
|||
waddch (dialog, ACS_HLINE); |
|||
wattrset (dialog, dialog_attr); |
|||
waddch (dialog, ACS_RTEE); |
|||
|
|||
if (title != NULL && strlen(title) >= width-2 ) { |
|||
/* truncate long title -- mec */ |
|||
char * title2 = malloc(width-2+1); |
|||
memcpy( title2, title, width-2 ); |
|||
title2[width-2] = '\0'; |
|||
title = title2; |
|||
} |
|||
|
|||
if (title != NULL) { |
|||
wattrset (dialog, title_attr); |
|||
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); |
|||
waddstr (dialog, (char *)title); |
|||
waddch (dialog, ' '); |
|||
} |
|||
|
|||
wattrset (dialog, dialog_attr); |
|||
print_autowrap (dialog, prompt, width - 2, 1, 3); |
|||
|
|||
list_width = width - 6; |
|||
box_y = height - list_height - 5; |
|||
box_x = (width - list_width) / 2 - 1; |
|||
|
|||
/* create new window for the list */ |
|||
list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1); |
|||
|
|||
keypad (list, TRUE); |
|||
|
|||
/* draw a box around the list items */ |
|||
draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2, |
|||
menubox_border_attr, menubox_attr); |
|||
|
|||
/* Find length of longest item in order to center checklist */ |
|||
check_x = 0; |
|||
for (i = 0; i < item_no; i++) |
|||
check_x = MAX (check_x, + strlen (items[i * 3 + 1]) + 4); |
|||
|
|||
check_x = (list_width - check_x) / 2; |
|||
item_x = check_x + 4; |
|||
|
|||
if (choice >= list_height) { |
|||
scroll = choice - list_height + 1; |
|||
choice -= scroll; |
|||
} |
|||
|
|||
/* Print the list */ |
|||
for (i = 0; i < max_choice; i++) { |
|||
print_item (list, items[(scroll+i) * 3 + 1], |
|||
status[i+scroll], i, i == choice); |
|||
} |
|||
|
|||
print_arrows(dialog, choice, item_no, scroll, |
|||
box_y, box_x + check_x + 5, list_height); |
|||
|
|||
print_buttons(dialog, height, width, 0); |
|||
|
|||
wnoutrefresh (list); |
|||
wnoutrefresh (dialog); |
|||
doupdate (); |
|||
|
|||
while (key != ESC) { |
|||
key = wgetch (dialog); |
|||
|
|||
for (i = 0; i < max_choice; i++) |
|||
if (toupper(key) == toupper(items[(scroll+i)*3+1][0])) |
|||
break; |
|||
|
|||
|
|||
if ( i < max_choice || key == KEY_UP || key == KEY_DOWN || |
|||
key == '+' || key == '-' ) { |
|||
if (key == KEY_UP || key == '-') { |
|||
if (!choice) { |
|||
if (!scroll) |
|||
continue; |
|||
/* Scroll list down */ |
|||
if (list_height > 1) { |
|||
/* De-highlight current first item */ |
|||
print_item (list, items[scroll * 3 + 1], |
|||
status[scroll], 0, FALSE); |
|||
scrollok (list, TRUE); |
|||
wscrl (list, -1); |
|||
scrollok (list, FALSE); |
|||
} |
|||
scroll--; |
|||
print_item (list, items[scroll * 3 + 1], |
|||
status[scroll], 0, TRUE); |
|||
wnoutrefresh (list); |
|||
|
|||
print_arrows(dialog, choice, item_no, scroll, |
|||
box_y, box_x + check_x + 5, list_height); |
|||
|
|||
wrefresh (dialog); |
|||
|
|||
continue; /* wait for another key press */ |
|||
} else |
|||
i = choice - 1; |
|||
} else if (key == KEY_DOWN || key == '+') { |
|||
if (choice == max_choice - 1) { |
|||
if (scroll + choice >= item_no - 1) |
|||
continue; |
|||
/* Scroll list up */ |
|||
if (list_height > 1) { |
|||
/* De-highlight current last item before scrolling up */ |
|||
print_item (list, items[(scroll + max_choice - 1) * 3 + 1], |
|||
status[scroll + max_choice - 1], |
|||
max_choice - 1, FALSE); |
|||
scrollok (list, TRUE); |
|||
scroll (list); |
|||
scrollok (list, FALSE); |
|||
} |
|||
scroll++; |
|||
print_item (list, items[(scroll + max_choice - 1) * 3 + 1], |
|||
status[scroll + max_choice - 1], |
|||
max_choice - 1, TRUE); |
|||
wnoutrefresh (list); |
|||
|
|||
print_arrows(dialog, choice, item_no, scroll, |
|||
box_y, box_x + check_x + 5, list_height); |
|||
|
|||
wrefresh (dialog); |
|||
|
|||
continue; /* wait for another key press */ |
|||
} else |
|||
i = choice + 1; |
|||
} |
|||
if (i != choice) { |
|||
/* De-highlight current item */ |
|||
print_item (list, items[(scroll + choice) * 3 + 1], |
|||
status[scroll + choice], choice, FALSE); |
|||
/* Highlight new item */ |
|||
choice = i; |
|||
print_item (list, items[(scroll + choice) * 3 + 1], |
|||
status[scroll + choice], choice, TRUE); |
|||
wnoutrefresh (list); |
|||
wrefresh (dialog); |
|||
} |
|||
continue; /* wait for another key press */ |
|||
} |
|||
switch (key) { |
|||
case 'H': |
|||
case 'h': |
|||
case '?': |
|||
delwin (dialog); |
|||
free (status); |
|||
return 1; |
|||
case TAB: |
|||
case KEY_LEFT: |
|||
case KEY_RIGHT: |
|||
button = ((key == KEY_LEFT ? --button : ++button) < 0) |
|||
? 1 : (button > 1 ? 0 : button); |
|||
|
|||
print_buttons(dialog, height, width, button); |
|||
wrefresh (dialog); |
|||
break; |
|||
case 'S': |
|||
case 's': |
|||
case ' ': |
|||
case '\n': |
|||
if (!button) { |
|||
if (flag == FLAG_CHECK) { |
|||
status[scroll + choice] = !status[scroll + choice]; |
|||
wmove (list, choice, check_x); |
|||
wattrset (list, check_selected_attr); |
|||
wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' '); |
|||
} else { |
|||
if (!status[scroll + choice]) { |
|||
for (i = 0; i < item_no; i++) |
|||
status[i] = 0; |
|||
status[scroll + choice] = 1; |
|||
for (i = 0; i < max_choice; i++) |
|||
print_item (list, items[(scroll + i) * 3 + 1], |
|||
status[scroll + i], i, i == choice); |
|||
} |
|||
} |
|||
wnoutrefresh (list); |
|||
wrefresh (dialog); |
|||
|
|||
for (i = 0; i < item_no; i++) { |
|||
if (status[i]) { |
|||
if (flag == FLAG_CHECK) { |
|||
fprintf (stderr, "\"%s\" ", items[i * 3]); |
|||
} else { |
|||
fprintf (stderr, "%s", items[i * 3]); |
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
|||
delwin (dialog); |
|||
free (status); |
|||
return button; |
|||
case 'X': |
|||
case 'x': |
|||
key = ESC; |
|||
case ESC: |
|||
break; |
|||
} |
|||
|
|||
/* Now, update everything... */ |
|||
doupdate (); |
|||
} |
|||
|
|||
|
|||
delwin (dialog); |
|||
free (status); |
|||
return -1; /* ESC pressed */ |
|||
} |
@ -0,0 +1,161 @@ |
|||
/*
|
|||
* colors.h -- color attribute definitions |
|||
* |
|||
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |
|||
* |
|||
* 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 (at your option) 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. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|||
*/ |
|||
|
|||
|
|||
/*
|
|||
* Default color definitions |
|||
* |
|||
* *_FG = foreground |
|||
* *_BG = background |
|||
* *_HL = highlight? |
|||
*/ |
|||
#define SCREEN_FG COLOR_CYAN |
|||
#define SCREEN_BG COLOR_BLUE |
|||
#define SCREEN_HL TRUE |
|||
|
|||
#define SHADOW_FG COLOR_BLACK |
|||
#define SHADOW_BG COLOR_BLACK |
|||
#define SHADOW_HL TRUE |
|||
|
|||
#define DIALOG_FG COLOR_BLACK |
|||
#define DIALOG_BG COLOR_WHITE |
|||
#define DIALOG_HL FALSE |
|||
|
|||
#define TITLE_FG COLOR_YELLOW |
|||
#define TITLE_BG COLOR_WHITE |
|||
#define TITLE_HL TRUE |
|||
|
|||
#define BORDER_FG COLOR_WHITE |
|||
#define BORDER_BG COLOR_WHITE |
|||
#define BORDER_HL TRUE |
|||
|
|||
#define BUTTON_ACTIVE_FG COLOR_WHITE |
|||
#define BUTTON_ACTIVE_BG COLOR_BLUE |
|||
#define BUTTON_ACTIVE_HL TRUE |
|||
|
|||
#define BUTTON_INACTIVE_FG COLOR_BLACK |
|||
#define BUTTON_INACTIVE_BG COLOR_WHITE |
|||
#define BUTTON_INACTIVE_HL FALSE |
|||
|
|||
#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE |
|||
#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE |
|||
#define BUTTON_KEY_ACTIVE_HL TRUE |
|||
|
|||
#define BUTTON_KEY_INACTIVE_FG COLOR_RED |
|||
#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE |
|||
#define BUTTON_KEY_INACTIVE_HL FALSE |
|||
|
|||
#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW |
|||
#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE |
|||
#define BUTTON_LABEL_ACTIVE_HL TRUE |
|||
|
|||
#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK |
|||
#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE |
|||
#define BUTTON_LABEL_INACTIVE_HL TRUE |
|||
|
|||
#define INPUTBOX_FG COLOR_BLACK |
|||
#define INPUTBOX_BG COLOR_WHITE |
|||
#define INPUTBOX_HL FALSE |
|||
|
|||
#define INPUTBOX_BORDER_FG COLOR_BLACK |
|||
#define INPUTBOX_BORDER_BG COLOR_WHITE |
|||
#define INPUTBOX_BORDER_HL FALSE |
|||
|
|||
#define SEARCHBOX_FG COLOR_BLACK |
|||
#define SEARCHBOX_BG COLOR_WHITE |
|||
#define SEARCHBOX_HL FALSE |
|||
|
|||
#define SEARCHBOX_TITLE_FG COLOR_YELLOW |
|||
#define SEARCHBOX_TITLE_BG COLOR_WHITE |
|||
#define SEARCHBOX_TITLE_HL TRUE |
|||
|
|||
#define SEARCHBOX_BORDER_FG COLOR_WHITE |
|||
#define SEARCHBOX_BORDER_BG COLOR_WHITE |
|||
#define SEARCHBOX_BORDER_HL TRUE |
|||
|
|||
#define POSITION_INDICATOR_FG COLOR_YELLOW |
|||
#define POSITION_INDICATOR_BG COLOR_WHITE |
|||
#define POSITION_INDICATOR_HL TRUE |
|||
|
|||
#define MENUBOX_FG COLOR_BLACK |
|||
#define MENUBOX_BG COLOR_WHITE |
|||
#define MENUBOX_HL FALSE |
|||
|
|||
#define MENUBOX_BORDER_FG COLOR_WHITE |
|||
#define MENUBOX_BORDER_BG COLOR_WHITE |
|||
#define MENUBOX_BORDER_HL TRUE |
|||
|
|||
#define ITEM_FG COLOR_BLACK |
|||
#define ITEM_BG COLOR_WHITE |
|||
#define ITEM_HL FALSE |
|||
|
|||
#define ITEM_SELECTED_FG COLOR_WHITE |
|||
#define ITEM_SELECTED_BG COLOR_BLUE |
|||
#define ITEM_SELECTED_HL TRUE |
|||
|
|||
#define TAG_FG COLOR_YELLOW |
|||
#define TAG_BG COLOR_WHITE |
|||
#define TAG_HL TRUE |
|||
|
|||
#define TAG_SELECTED_FG COLOR_YELLOW |
|||
#define TAG_SELECTED_BG COLOR_BLUE |
|||
#define TAG_SELECTED_HL TRUE |
|||
|
|||
#define TAG_KEY_FG COLOR_YELLOW |
|||
#define TAG_KEY_BG COLOR_WHITE |
|||
#define TAG_KEY_HL TRUE |
|||
|
|||
#define TAG_KEY_SELECTED_FG COLOR_YELLOW |
|||
#define TAG_KEY_SELECTED_BG COLOR_BLUE |
|||
#define TAG_KEY_SELECTED_HL TRUE |
|||
|
|||
#define CHECK_FG COLOR_BLACK |
|||
#define CHECK_BG COLOR_WHITE |
|||
#define CHECK_HL FALSE |
|||
|
|||
#define CHECK_SELECTED_FG COLOR_WHITE |
|||
#define CHECK_SELECTED_BG COLOR_BLUE |
|||
#define CHECK_SELECTED_HL TRUE |
|||
|
|||
#define UARROW_FG COLOR_GREEN |
|||
#define UARROW_BG COLOR_WHITE |
|||
#define UARROW_HL TRUE |
|||
|
|||
#define DARROW_FG COLOR_GREEN |
|||
#define DARROW_BG COLOR_WHITE |
|||
#define DARROW_HL TRUE |
|||
|
|||
/* End of default color definitions */ |
|||
|
|||
#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y))) |
|||
#define COLOR_NAME_LEN 10 |
|||
#define COLOR_COUNT 8 |
|||
|
|||
/*
|
|||
* Global variables |
|||
*/ |
|||
|
|||
typedef struct { |
|||
char name[COLOR_NAME_LEN]; |
|||
int value; |
|||
} color_names_st; |
|||
|
|||
extern color_names_st color_names[]; |
|||
extern int color_table[][3]; |
@ -0,0 +1,184 @@ |
|||
|
|||
/*
|
|||
* dialog.h -- common declarations for all dialog modules |
|||
* |
|||
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |
|||
* |
|||
* 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 (at your option) 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. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|||
*/ |
|||
|
|||
#include <sys/types.h> |
|||
#include <fcntl.h> |
|||
#include <unistd.h> |
|||
#include <ctype.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
|
|||
#include CURSES_LOC |
|||
|
|||
/*
|
|||
* Colors in ncurses 1.9.9e do not work properly since foreground and |
|||
* background colors are OR'd rather than separately masked. This version |
|||
* of dialog was hacked to work with ncurses 1.9.9e, making it incompatible |
|||
* with standard curses. The simplest fix (to make this work with standard |
|||
* curses) uses the wbkgdset() function, not used in the original hack. |
|||
* Turn it off if we're building with 1.9.9e, since it just confuses things. |
|||
*/ |
|||
#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) |
|||
#define OLD_NCURSES 1 |
|||
#undef wbkgdset |
|||
#define wbkgdset(w,p) /*nothing*/ |
|||
#else |
|||
#define OLD_NCURSES 0 |
|||
#endif |
|||
|
|||
#define TR(params) _tracef params |
|||
|
|||
#define ESC 27 |
|||
#define TAB 9 |
|||
#define MAX_LEN 2048 |
|||
#define BUF_SIZE (10*1024) |
|||
#define MIN(x,y) (x < y ? x : y) |
|||
#define MAX(x,y) (x > y ? x : y) |
|||
|
|||
|
|||
#ifndef ACS_ULCORNER |
|||
#define ACS_ULCORNER '+' |
|||
#endif |
|||
#ifndef ACS_LLCORNER |
|||
#define ACS_LLCORNER '+' |
|||
#endif |
|||
#ifndef ACS_URCORNER |
|||
#define ACS_URCORNER '+' |
|||
#endif |
|||
#ifndef ACS_LRCORNER |
|||
#define ACS_LRCORNER '+' |
|||
#endif |
|||
#ifndef ACS_HLINE |
|||
#define ACS_HLINE '-' |
|||
#endif |
|||
#ifndef ACS_VLINE |
|||
#define ACS_VLINE '|' |
|||
#endif |
|||
#ifndef ACS_LTEE |
|||
#define ACS_LTEE '+' |
|||
#endif |
|||
#ifndef ACS_RTEE |
|||
#define ACS_RTEE '+' |
|||
#endif |
|||
#ifndef ACS_UARROW |
|||
#define ACS_UARROW '^' |
|||
#endif |
|||
#ifndef ACS_DARROW |
|||
#define ACS_DARROW 'v' |
|||
#endif |
|||
|
|||
/*
|
|||
* Attribute names |
|||
*/ |
|||
#define screen_attr attributes[0] |
|||
#define shadow_attr attributes[1] |
|||
#define dialog_attr attributes[2] |
|||
#define title_attr attributes[3] |
|||
#define border_attr attributes[4] |
|||
#define button_active_attr attributes[5] |
|||
#define button_inactive_attr attributes[6] |
|||
#define button_key_active_attr attributes[7] |
|||
#define button_key_inactive_attr attributes[8] |
|||
#define button_label_active_attr attributes[9] |
|||
#define button_label_inactive_attr attributes[10] |
|||
#define inputbox_attr attributes[11] |
|||
#define inputbox_border_attr attributes[12] |
|||
#define searchbox_attr attributes[13] |
|||
#define searchbox_title_attr attributes[14] |
|||
#define searchbox_border_attr attributes[15] |
|||
#define position_indicator_attr attributes[16] |
|||
#define menubox_attr attributes[17] |
|||
#define menubox_border_attr attributes[18] |
|||
#define item_attr attributes[19] |
|||
#define item_selected_attr attributes[20] |
|||
#define tag_attr attributes[21] |
|||
#define tag_selected_attr attributes[22] |
|||
#define tag_key_attr attributes[23] |
|||
#define tag_key_selected_attr attributes[24] |
|||
#define check_attr attributes[25] |
|||
#define check_selected_attr attributes[26] |
|||
#define uarrow_attr attributes[27] |
|||
#define darrow_attr attributes[28] |
|||
|
|||
/* number of attributes */ |
|||
#define ATTRIBUTE_COUNT 29 |
|||
|
|||
/*
|
|||
* Global variables |
|||
*/ |
|||
extern bool use_colors; |
|||
extern bool use_shadow; |
|||
|
|||
extern chtype attributes[]; |
|||
|
|||
extern const char *backtitle; |
|||
|
|||
/*
|
|||
* Function prototypes |
|||
*/ |
|||
extern void create_rc (const char *filename); |
|||
extern int parse_rc (void); |
|||
|
|||
|
|||
void init_dialog (void); |
|||
void end_dialog (void); |
|||
void attr_clear (WINDOW * win, int height, int width, chtype attr); |
|||
void dialog_clear (void); |
|||
void color_setup (void); |
|||
void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x); |
|||
void print_button (WINDOW * win, const char *label, int y, int x, int selected); |
|||
void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box, |
|||
chtype border); |
|||
void draw_shadow (WINDOW * win, int y, int x, int height, int width); |
|||
|
|||
int first_alpha (const char *string, const char *exempt); |
|||
int dialog_yesno (const char *title, const char *prompt, int height, int width); |
|||
int dialog_msgbox (const char *title, const char *prompt, int height, |
|||
int width, int pause); |
|||
int dialog_textbox (const char *title, const char *file, int height, int width); |
|||
int dialog_menu (const char *title, const char *prompt, int height, int width, |
|||
int menu_height, const char *choice, int item_no, |
|||
const char * const * items); |
|||
int dialog_checklist (const char *title, const char *prompt, int height, |
|||
int width, int list_height, int item_no, |
|||
const char * const * items, int flag); |
|||
extern unsigned char dialog_input_result[]; |
|||
int dialog_inputbox (const char *title, const char *prompt, int height, |
|||
int width, const char *init); |
|||
|
|||
/*
|
|||
* This is the base for fictitious keys, which activate |
|||
* the buttons. |
|||
* |
|||
* Mouse-generated keys are the following: |
|||
* -- the first 32 are used as numbers, in addition to '0'-'9' |
|||
* -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') |
|||
* -- uppercase chars are used to invoke the button (M_EVENT + 'O') |
|||
*/ |
|||
#define M_EVENT (KEY_MAX+1) |
|||
|
|||
|
|||
/*
|
|||
* The `flag' parameter in checklist is used to select between |
|||
* radiolist and checklist |
|||
*/ |
|||
#define FLAG_CHECK 1 |
|||
#define FLAG_RADIO 0 |
@ -0,0 +1,240 @@ |
|||
/*
|
|||
* inputbox.c -- implements the input box |
|||
* |
|||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |
|||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) |
|||
* |
|||
* 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 (at your option) 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. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|||
*/ |
|||
|
|||
#include "dialog.h" |
|||
|
|||
unsigned char dialog_input_result[MAX_LEN + 1]; |
|||
|
|||
/*
|
|||
* Print the termination buttons |
|||
*/ |
|||
static void |
|||
print_buttons(WINDOW *dialog, int height, int width, int selected) |
|||
{ |
|||
int x = width / 2 - 11; |
|||
int y = height - 2; |
|||
|
|||
print_button (dialog, " Ok ", y, x, selected==0); |
|||
print_button (dialog, " Help ", y, x + 14, selected==1); |
|||
|
|||
wmove(dialog, y, x+1+14*selected); |
|||
wrefresh(dialog); |
|||
} |
|||
|
|||
/*
|
|||
* Display a dialog box for inputing a string |
|||
*/ |
|||
int |
|||
dialog_inputbox (const char *title, const char *prompt, int height, int width, |
|||
const char *init) |
|||
{ |
|||
int i, x, y, box_y, box_x, box_width; |
|||
int input_x = 0, scroll = 0, key = 0, button = -1; |
|||
unsigned char *instr = dialog_input_result; |
|||
WINDOW *dialog; |
|||
|
|||
/* center dialog box on screen */ |
|||
x = (COLS - width) / 2; |
|||
y = (LINES - height) / 2; |
|||
|
|||
|
|||
draw_shadow (stdscr, y, x, height, width); |
|||
|
|||
dialog = newwin (height, width, y, x); |
|||
keypad (dialog, TRUE); |
|||
|
|||
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); |
|||
wattrset (dialog, border_attr); |
|||
mvwaddch (dialog, height-3, 0, ACS_LTEE); |
|||
for (i = 0; i < width - 2; i++) |
|||
waddch (dialog, ACS_HLINE); |
|||
wattrset (dialog, dialog_attr); |
|||
waddch (dialog, ACS_RTEE); |
|||
|
|||
if (title != NULL && strlen(title) >= width-2 ) { |
|||
/* truncate long title -- mec */ |
|||
char * title2 = malloc(width-2+1); |
|||
memcpy( title2, title, width-2 ); |
|||
title2[width-2] = '\0'; |
|||
title = title2; |
|||
} |
|||
|
|||
if (title != NULL) { |
|||
wattrset (dialog, title_attr); |
|||
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); |
|||
waddstr (dialog, (char *)title); |
|||
waddch (dialog, ' '); |
|||
} |
|||
|
|||
wattrset (dialog, dialog_attr); |
|||
print_autowrap (dialog, prompt, width - 2, 1, 3); |
|||
|
|||
/* Draw the input field box */ |
|||
box_width = width - 6; |
|||
getyx (dialog, y, x); |
|||
box_y = y + 2; |
|||
box_x = (width - box_width) / 2; |
|||
draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2, |
|||
border_attr, dialog_attr); |
|||
|
|||
print_buttons(dialog, height, width, 0); |
|||
|
|||
/* Set up the initial value */ |
|||
wmove (dialog, box_y, box_x); |
|||
wattrset (dialog, inputbox_attr); |
|||
|
|||
if (!init) |
|||
instr[0] = '\0'; |
|||
else |
|||
strcpy (instr, init); |
|||
|
|||
input_x = strlen (instr); |
|||
|
|||
if (input_x >= box_width) { |
|||
scroll = input_x - box_width + 1; |
|||
input_x = box_width - 1; |
|||
for (i = 0; i < box_width - 1; i++) |
|||
waddch (dialog, instr[scroll + i]); |
|||
} else |
|||
waddstr (dialog, instr); |
|||
|
|||
wmove (dialog, box_y, box_x + input_x); |
|||
|
|||
wrefresh (dialog); |
|||
|
|||
while (key != ESC) { |
|||
key = wgetch (dialog); |
|||
|
|||
if (button == -1) { /* Input box selected */ |
|||
switch (key) { |
|||
case TAB: |
|||
case KEY_UP: |
|||
case KEY_DOWN: |
|||
break; |
|||
case KEY_LEFT: |
|||
continue; |
|||
case KEY_RIGHT: |
|||
continue; |
|||
case KEY_BACKSPACE: |
|||
case 127: |
|||
if (input_x || scroll) { |
|||
wattrset (dialog, inputbox_attr); |
|||
if (!input_x) { |
|||
scroll = scroll < box_width - 1 ? |
|||
0 : scroll - (box_width - 1); |
|||
wmove (dialog, box_y, box_x); |
|||
for (i = 0; i < box_width; i++) |
|||
waddch (dialog, instr[scroll + input_x + i] ? |
|||
instr[scroll + input_x + i] : ' '); |
|||
input_x = strlen (instr) - scroll; |
|||
} else |
|||
input_x--; |
|||
instr[scroll + input_x] = '\0'; |
|||
mvwaddch (dialog, box_y, input_x + box_x, ' '); |
|||
wmove (dialog, box_y, input_x + box_x); |
|||
wrefresh (dialog); |
|||
} |
|||
continue; |
|||
default: |
|||
if (key < 0x100 && isprint (key)) { |
|||
if (scroll + input_x < MAX_LEN) { |
|||
wattrset (dialog, inputbox_attr); |
|||
instr[scroll + input_x] = key; |
|||
instr[scroll + input_x + 1] = '\0'; |
|||
if (input_x == box_width - 1) { |
|||
scroll++; |
|||
wmove (dialog, box_y, box_x); |
|||
for (i = 0; i < box_width - 1; i++) |
|||
waddch (dialog, instr[scroll + i]); |
|||
} else { |
|||
wmove (dialog, box_y, input_x++ + box_x); |
|||
waddch (dialog, key); |
|||
} |
|||
wrefresh (dialog); |
|||
} else |
|||
flash (); /* Alarm user about overflow */ |
|||
continue; |
|||
} |
|||
} |
|||
} |
|||
switch (key) { |
|||
case 'O': |
|||
case 'o': |
|||
delwin (dialog); |
|||
return 0; |
|||
case 'H': |
|||
case 'h': |
|||
delwin (dialog); |
|||
return 1; |
|||
case KEY_UP: |
|||
case KEY_LEFT: |
|||
switch (button) { |
|||
case -1: |
|||
button = 1; /* Indicates "Cancel" button is selected */ |
|||
print_buttons(dialog, height, width, 1); |
|||
break; |
|||
case 0: |
|||
button = -1; /* Indicates input box is selected */ |
|||
print_buttons(dialog, height, width, 0); |
|||
wmove (dialog, box_y, box_x + input_x); |
|||
wrefresh (dialog); |
|||
break; |
|||
case 1: |
|||
button = 0; /* Indicates "OK" button is selected */ |
|||
print_buttons(dialog, height, width, 0); |
|||
break; |
|||
} |
|||
break; |
|||
case TAB: |
|||
case KEY_DOWN: |
|||
case KEY_RIGHT: |
|||
switch (button) { |
|||
case -1: |
|||
button = 0; /* Indicates "OK" button is selected */ |
|||
print_buttons(dialog, height, width, 0); |
|||
break; |
|||
case 0: |
|||
button = 1; /* Indicates "Cancel" button is selected */ |
|||
print_buttons(dialog, height, width, 1); |
|||
break; |
|||
case 1: |
|||
button = -1; /* Indicates input box is selected */ |
|||
print_buttons(dialog, height, width, 0); |
|||
wmove (dialog, box_y, box_x + input_x); |
|||
wrefresh (dialog); |
|||
break; |
|||
} |
|||
break; |
|||
case ' ': |
|||
case '\n': |
|||
delwin (dialog); |
|||
return (button == -1 ? 0 : button); |
|||
case 'X': |
|||
case 'x': |
|||
key = ESC; |
|||
case ESC: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
delwin (dialog); |
|||
return -1; /* ESC pressed */ |
|||
} |
@ -0,0 +1,226 @@ |
|||
/*
|
|||
* dialog - Display simple dialog boxes from shell scripts |
|||
* |
|||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |
|||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) |
|||
* |
|||
* 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 (at your option) 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. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|||
*/ |
|||
|
|||
#include "dialog.h" |
|||
|
|||
static void Usage (const char *name); |
|||
|
|||
typedef int (jumperFn) (const char *title, int argc, const char * const * argv); |
|||
|
|||
struct Mode { |
|||
char *name; |
|||
int argmin, argmax, argmod; |
|||
jumperFn *jumper; |
|||
}; |
|||
|
|||
jumperFn j_menu, j_checklist, j_radiolist, j_yesno, j_textbox, j_inputbox; |
|||
jumperFn j_msgbox, j_infobox; |
|||
|
|||
static struct Mode modes[] = |
|||
{ |
|||
{"--menu", 9, 0, 3, j_menu}, |
|||
{"--checklist", 9, 0, 3, j_checklist}, |
|||
{"--radiolist", 9, 0, 3, j_radiolist}, |
|||
{"--yesno", 5,5,1, j_yesno}, |
|||
{"--textbox", 5,5,1, j_textbox}, |
|||
{"--inputbox", 5, 6, 1, j_inputbox}, |
|||
{"--msgbox", 5, 5, 1, j_msgbox}, |
|||
{"--infobox", 5, 5, 1, j_infobox}, |
|||
{NULL, 0, 0, 0, NULL} |
|||
}; |
|||
|
|||
static struct Mode *modePtr; |
|||
|
|||
#ifdef LOCALE |
|||
#include <locale.h> |
|||
#endif |
|||
|
|||
int |
|||
main (int argc, const char * const * argv) |
|||
{ |
|||
int offset = 0, clear_screen = 0, end_common_opts = 0, retval; |
|||
const char *title = NULL; |
|||
|
|||
#ifdef LOCALE |
|||
(void) setlocale (LC_ALL, ""); |
|||
#endif |
|||
|
|||
#ifdef TRACE |
|||
trace(TRACE_CALLS|TRACE_UPDATE); |
|||
#endif |
|||
if (argc < 2) { |
|||
Usage (argv[0]); |
|||
exit (-1); |
|||
} |
|||
|
|||
while (offset < argc - 1 && !end_common_opts) { /* Common options */ |
|||
if (!strcmp (argv[offset + 1], "--title")) { |
|||
if (argc - offset < 3 || title != NULL) { |
|||
Usage (argv[0]); |
|||
exit (-1); |
|||
} else { |
|||
title = argv[offset + 2]; |
|||
offset += 2; |
|||
} |
|||
} else if (!strcmp (argv[offset + 1], "--backtitle")) { |
|||
if (backtitle != NULL) { |
|||
Usage (argv[0]); |
|||
exit (-1); |
|||
} else { |
|||
backtitle = argv[offset + 2]; |
|||
offset += 2; |
|||
} |
|||
} else if (!strcmp (argv[offset + 1], "--clear")) { |
|||
if (clear_screen) { /* Hey, "--clear" can't appear twice! */ |
|||
Usage (argv[0]); |
|||
exit (-1); |
|||
} else if (argc == 2) { /* we only want to clear the screen */ |
|||
init_dialog (); |
|||
refresh (); /* init_dialog() will clear the screen for us */ |
|||
end_dialog (); |
|||
return 0; |
|||
} else { |
|||
clear_screen = 1; |
|||
offset++; |
|||
} |
|||
} else /* no more common options */ |
|||
end_common_opts = 1; |
|||
} |
|||
|
|||
if (argc - 1 == offset) { /* no more options */ |
|||
Usage (argv[0]); |
|||
exit (-1); |
|||
} |
|||
/* use a table to look for the requested mode, to avoid code duplication */ |
|||
|
|||
for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */ |
|||
if (!strcmp (argv[offset + 1], modePtr->name)) |
|||
break; |
|||
|
|||
if (!modePtr->name) |
|||
Usage (argv[0]); |
|||
if (argc - offset < modePtr->argmin) |
|||
Usage (argv[0]); |
|||
if (modePtr->argmax && argc - offset > modePtr->argmax) |
|||
Usage (argv[0]); |
|||
|
|||
|
|||
|
|||
init_dialog (); |
|||
retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset); |
|||
|
|||
if (clear_screen) { /* clear screen before exit */ |
|||
attr_clear (stdscr, LINES, COLS, screen_attr); |
|||
refresh (); |
|||
} |
|||
end_dialog(); |
|||
|
|||
exit (retval); |
|||
} |
|||
|
|||
/*
|
|||
* Print program usage |
|||
*/ |
|||
static void |
|||
Usage (const char *name) |
|||
{ |
|||
fprintf (stderr, "\
|
|||
\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\ |
|||
\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\ |
|||
\n modified/gutted for use as a Linux kernel config tool by \ |
|||
\n William Roadcap (roadcapw@cfw.com)\ |
|||
\n\ |
|||
\n* Display dialog boxes from shell scripts *\ |
|||
\n\ |
|||
\nUsage: %s --clear\ |
|||
\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\ |
|||
\n\ |
|||
\nBox options:\ |
|||
\n\ |
|||
\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\ |
|||
\n --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\ |
|||
\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\ |
|||
\n --textbox <file> <height> <width>\ |
|||
\n --inputbox <text> <height> <width> [<init>]\ |
|||
\n --yesno <text> <height> <width>\ |
|||
\n", name, name); |
|||
exit (-1); |
|||
} |
|||
|
|||
/*
|
|||
* These are the program jumpers |
|||
*/ |
|||
|
|||
int |
|||
j_menu (const char *t, int ac, const char * const * av) |
|||
{ |
|||
return dialog_menu (t, av[2], atoi (av[3]), atoi (av[4]), |
|||
atoi (av[5]), av[6], (ac - 6) / 2, av + 7); |
|||
} |
|||
|
|||
int |
|||
j_checklist (const char *t, int ac, const char * const * av) |
|||
{ |
|||
return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]), |
|||
atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_CHECK); |
|||
} |
|||
|
|||
int |
|||
j_radiolist (const char *t, int ac, const char * const * av) |
|||
{ |
|||
return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]), |
|||
atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_RADIO); |
|||
} |
|||
|
|||
int |
|||
j_textbox (const char *t, int ac, const char * const * av) |
|||
{ |
|||
return dialog_textbox (t, av[2], atoi (av[3]), atoi (av[4])); |
|||
} |
|||
|
|||
int |
|||
j_yesno (const char *t, int ac, const char * const * av) |
|||
{ |
|||
return dialog_yesno (t, av[2], atoi (av[3]), atoi (av[4])); |
|||
} |
|||
|
|||
int |
|||
j_inputbox (const char *t, int ac, const char * const * av) |
|||
{ |
|||
int ret = dialog_inputbox (t, av[2], atoi (av[3]), atoi (av[4]), |
|||
ac == 6 ? av[5] : (char *) NULL); |
|||
if (ret == 0) |
|||
fprintf(stderr, dialog_input_result); |
|||
return ret; |
|||
} |
|||
|
|||
int |
|||
j_msgbox (const char *t, int ac, const char * const * av) |
|||
{ |
|||
return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 1); |
|||
} |
|||
|
|||
int |
|||
j_infobox (const char *t, int ac, const char * const * av) |
|||
{ |
|||
return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 0); |
|||
} |
|||
|
@ -0,0 +1,443 @@ |
|||
/*
|
|||
* menubox.c -- implements the menu box |
|||
* |
|||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |
|||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) |
|||
* |
|||
* 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 (at your option) 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. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|||
*/ |
|||
|
|||
/*
|
|||
* Changes by Clifford Wolf (god@clifford.at) |
|||
* |
|||
* [ 1998-06-13 ] |
|||
* |
|||
* *) A bugfix for the Page-Down problem |
|||
* |
|||
* *) Formerly when I used Page Down and Page Up, the cursor would be set |
|||
* to the first position in the menu box. Now lxdialog is a bit |
|||
* smarter and works more like other menu systems (just have a look at |
|||
* it). |
|||
* |
|||
* *) Formerly if I selected something my scrolling would be broken because |
|||
* lxdialog is re-invoked by the Menuconfig shell script, can't |
|||
* remember the last scrolling position, and just sets it so that the |
|||
* cursor is at the bottom of the box. Now it writes the temporary file |
|||
* lxdialog.scrltmp which contains this information. The file is |
|||
* deleted by lxdialog if the user leaves a submenu or enters a new |
|||
* one, but it would be nice if Menuconfig could make another "rm -f" |
|||
* just to be sure. Just try it out - you will recognise a difference! |
|||
* |
|||
* [ 1998-06-14 ] |
|||
* |
|||
* *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files |
|||
* and menus change their size on the fly. |
|||
* |
|||
* *) If for some reason the last scrolling position is not saved by |
|||
* lxdialog, it sets the scrolling so that the selected item is in the |
|||
* middle of the menu box, not at the bottom. |
|||
* |
|||
* 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) |
|||
* Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. |
|||
* This fixes a bug in Menuconfig where using ' ' to descend into menus |
|||
* would leave mis-synchronized lxdialog.scrltmp files lying around, |
|||
* fscanf would read in 'scroll', and eventually that value would get used. |
|||
*/ |
|||
|
|||
#include "dialog.h" |
|||
|
|||
static int menu_width, item_x; |
|||
|
|||
/*
|
|||
* Print menu item |
|||
*/ |
|||
static void |
|||
print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey) |
|||
{ |
|||
int j; |
|||
char menu_item[menu_width+1]; |
|||
|
|||
strncpy(menu_item, item, menu_width); |
|||
menu_item[menu_width] = 0; |
|||
j = first_alpha(menu_item, "YyNnMm"); |
|||
|
|||
/* Clear 'residue' of last item */ |
|||
wattrset (win, menubox_attr); |
|||
wmove (win, choice, 0); |
|||
#if OLD_NCURSES |
|||
{ |
|||
int i; |
|||
for (i = 0; i < menu_width; i++) |
|||
waddch (win, ' '); |
|||
} |
|||
#else |
|||
wclrtoeol(win); |
|||
#endif |
|||
wattrset (win, selected ? item_selected_attr : item_attr); |
|||
mvwaddstr (win, choice, item_x, menu_item); |
|||
if (hotkey) { |
|||
wattrset (win, selected ? tag_key_selected_attr : tag_key_attr); |
|||
mvwaddch(win, choice, item_x+j, menu_item[j]); |
|||
} |
|||
if (selected) { |
|||
wmove (win, choice, item_x+1); |
|||
wrefresh (win); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Print the scroll indicators. |
|||
*/ |
|||
static void |
|||
print_arrows (WINDOW * win, int item_no, int scroll, |
|||
int y, int x, int height) |
|||
{ |
|||
int cur_y, cur_x; |
|||
|
|||
getyx(win, cur_y, cur_x); |
|||
|
|||
wmove(win, y, x); |
|||
|
|||
if (scroll > 0) { |
|||
wattrset (win, uarrow_attr); |
|||
waddch (win, ACS_UARROW); |
|||
waddstr (win, "(-)"); |
|||
} |
|||
else { |
|||
wattrset (win, menubox_attr); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
} |
|||
|
|||
y = y + height + 1; |
|||
wmove(win, y, x); |
|||
|
|||
if ((height < item_no) && (scroll + height < item_no)) { |
|||
wattrset (win, darrow_attr); |
|||
waddch (win, ACS_DARROW); |
|||
waddstr (win, "(+)"); |
|||
} |
|||
else { |
|||
wattrset (win, menubox_border_attr); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
waddch (win, ACS_HLINE); |
|||
} |
|||
|
|||
wmove(win, cur_y, cur_x); |
|||
} |
|||
|
|||
/*
|
|||
* Display the termination buttons. |
|||
*/ |
|||
static void |
|||
print_buttons (WINDOW *win, int height, int width, int selected) |
|||
{ |
|||
int x = width / 2 - 16; |
|||
int y = height - 2; |
|||
|
|||
print_button (win, "Select", y, x, selected == 0); |
|||
print_button (win, " Exit ", y, x + 12, selected == 1); |
|||
print_button (win, " Help ", y, x + 24, selected == 2); |
|||
|
|||
wmove(win, y, x+1+12*selected); |
|||
wrefresh (win); |
|||
} |
|||
|
|||
/*
|
|||
* Display a menu for choosing among a number of options |
|||
*/ |
|||
int |
|||
dialog_menu (const char *title, const char *prompt, int height, int width, |
|||
int menu_height, const char *current, int item_no, |
|||
const char * const * items) |
|||
|
|||
{ |
|||
int i, j, x, y, box_x, box_y; |
|||
int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice; |
|||
WINDOW *dialog, *menu; |
|||
FILE *f; |
|||
|
|||
max_choice = MIN (menu_height, item_no); |
|||
|
|||
/* center dialog box on screen */ |
|||
x = (COLS - width) / 2; |
|||
y = (LINES - height) / 2; |
|||
|
|||
draw_shadow (stdscr, y, x, height, width); |
|||
|
|||
dialog = newwin (height, width, y, x); |
|||
keypad (dialog, TRUE); |
|||
|
|||
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); |
|||
wattrset (dialog, border_attr); |
|||
mvwaddch (dialog, height - 3, 0, ACS_LTEE); |
|||
for (i = 0; i < width - 2; i++) |
|||
waddch (dialog, ACS_HLINE); |
|||
wattrset (dialog, dialog_attr); |
|||
wbkgdset (dialog, dialog_attr & A_COLOR); |
|||
waddch (dialog, ACS_RTEE); |
|||
|
|||
if (title != NULL && strlen(title) >= width-2 ) { |
|||
/* truncate long title -- mec */ |
|||
char * title2 = malloc(width-2+1); |
|||
memcpy( title2, title, width-2 ); |
|||
title2[width-2] = '\0'; |
|||
title = title2; |
|||
} |
|||
|
|||
if (title != NULL) { |
|||
wattrset (dialog, title_attr); |
|||
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); |
|||
waddstr (dialog, (char *)title); |
|||
waddch (dialog, ' '); |
|||
} |
|||
|
|||
wattrset (dialog, dialog_attr); |
|||
print_autowrap (dialog, prompt, width - 2, 1, 3); |
|||
|
|||
menu_width = width - 6; |
|||
box_y = height - menu_height - 5; |
|||
box_x = (width - menu_width) / 2 - 1; |
|||
|
|||
/* create new window for the menu */ |
|||
menu = subwin (dialog, menu_height, menu_width, |
|||
y + box_y + 1, x + box_x + 1); |
|||
keypad (menu, TRUE); |
|||
|
|||
/* draw a box around the menu items */ |
|||
draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2, |
|||
menubox_border_attr, menubox_attr); |
|||
|
|||
/*
|
|||
* Find length of longest item in order to center menu. |
|||
* Set 'choice' to default item. |
|||
*/ |
|||
item_x = 0; |
|||
for (i = 0; i < item_no; i++) { |
|||
item_x = MAX (item_x, MIN(menu_width, strlen (items[i * 2 + 1]) + 2)); |
|||
if (strcmp(current, items[i*2]) == 0) choice = i; |
|||
} |
|||
|
|||
item_x = (menu_width - item_x) / 2; |
|||
|
|||
/* get the scroll info from the temp file */ |
|||
if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) { |
|||
if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) && |
|||
(scroll+max_choice > choice) && (scroll >= 0) && |
|||
(scroll+max_choice <= item_no) ) { |
|||
first_item = scroll; |
|||
choice = choice - scroll; |
|||
fclose(f); |
|||
} else { |
|||
scroll=0; |
|||
remove("lxdialog.scrltmp"); |
|||
fclose(f); |
|||
f=NULL; |
|||
} |
|||
} |
|||
if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) { |
|||
if (choice >= item_no-max_choice/2) |
|||
scroll = first_item = item_no-max_choice; |
|||
else |
|||
scroll = first_item = choice - max_choice/2; |
|||
choice = choice - scroll; |
|||
} |
|||
|
|||
/* Print the menu */ |
|||
for (i=0; i < max_choice; i++) { |
|||
print_item (menu, items[(first_item + i) * 2 + 1], i, i == choice, |
|||
(items[(first_item + i)*2][0] != ':')); |
|||
} |
|||
|
|||
wnoutrefresh (menu); |
|||
|
|||
print_arrows(dialog, item_no, scroll, |
|||
box_y, box_x+item_x+1, menu_height); |
|||
|
|||
print_buttons (dialog, height, width, 0); |
|||
wmove (menu, choice, item_x+1); |
|||
wrefresh (menu); |
|||
|
|||
while (key != ESC) { |
|||
key = wgetch(menu); |
|||
|
|||
if (key < 256 && isalpha(key)) key = tolower(key); |
|||
|
|||
if (strchr("ynm", key)) |
|||
i = max_choice; |
|||
else { |
|||
for (i = choice+1; i < max_choice; i++) { |
|||
j = first_alpha(items[(scroll+i)*2+1], "YyNnMm"); |
|||
if (key == tolower(items[(scroll+i)*2+1][j])) |
|||
break; |
|||
} |
|||
if (i == max_choice) |
|||
for (i = 0; i < max_choice; i++) { |
|||
j = first_alpha(items[(scroll+i)*2+1], "YyNnMm"); |
|||
if (key == tolower(items[(scroll+i)*2+1][j])) |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (i < max_choice || |
|||
key == KEY_UP || key == KEY_DOWN || |
|||
key == '-' || key == '+' || |
|||
key == KEY_PPAGE || key == KEY_NPAGE) { |
|||
|
|||
print_item (menu, items[(scroll+choice)*2+1], choice, FALSE, |
|||
(items[(scroll+choice)*2][0] != ':')); |
|||
|
|||
if (key == KEY_UP || key == '-') { |
|||
if (choice < 2 && scroll) { |
|||
/* Scroll menu down */ |
|||
scrollok (menu, TRUE); |
|||
wscrl (menu, -1); |
|||
scrollok (menu, FALSE); |
|||
|
|||
scroll--; |
|||
|
|||
print_item (menu, items[scroll * 2 + 1], 0, FALSE, |
|||
(items[scroll*2][0] != ':')); |
|||
} else |
|||
choice = MAX(choice - 1, 0); |
|||
|
|||
} else if (key == KEY_DOWN || key == '+') { |
|||
|
|||
print_item (menu, items[(scroll+choice)*2+1], choice, FALSE, |
|||
(items[(scroll+choice)*2][0] != ':')); |
|||
|
|||
if ((choice > max_choice-3) && |
|||
(scroll + max_choice < item_no) |
|||
) { |
|||
/* Scroll menu up */ |
|||
scrollok (menu, TRUE); |
|||
scroll (menu); |
|||
scrollok (menu, FALSE); |
|||
|
|||
scroll++; |
|||
|
|||
print_item (menu, items[(scroll+max_choice-1)*2+1], |
|||
max_choice-1, FALSE, |
|||
(items[(scroll+max_choice-1)*2][0] != ':')); |
|||
} else |
|||
choice = MIN(choice+1, max_choice-1); |
|||
|
|||
} else if (key == KEY_PPAGE) { |
|||
scrollok (menu, TRUE); |
|||
for (i=0; (i < max_choice); i++) { |
|||
if (scroll > 0) { |
|||
wscrl (menu, -1); |
|||
scroll--; |
|||
print_item (menu, items[scroll * 2 + 1], 0, FALSE, |
|||
(items[scroll*2][0] != ':')); |
|||
} else { |
|||
if (choice > 0) |
|||
choice--; |
|||
} |
|||
} |
|||
scrollok (menu, FALSE); |
|||
|
|||
} else if (key == KEY_NPAGE) { |
|||
for (i=0; (i < max_choice); i++) { |
|||
if (scroll+max_choice < item_no) { |
|||
scrollok (menu, TRUE); |
|||
scroll(menu); |
|||
scrollok (menu, FALSE); |
|||
scroll++; |
|||
print_item (menu, items[(scroll+max_choice-1)*2+1], |
|||
max_choice-1, FALSE, |
|||
(items[(scroll+max_choice-1)*2][0] != ':')); |
|||
} else { |
|||
if (choice+1 < max_choice) |
|||
choice++; |
|||
} |
|||
} |
|||
|
|||
} else |
|||
choice = i; |
|||
|
|||
print_item (menu, items[(scroll+choice)*2+1], choice, TRUE, |
|||
(items[(scroll+choice)*2][0] != ':')); |
|||
|
|||
print_arrows(dialog, item_no, scroll, |
|||
box_y, box_x+item_x+1, menu_height); |
|||
|
|||
wnoutrefresh (dialog); |
|||
wrefresh (menu); |
|||
|
|||
continue; /* wait for another key press */ |
|||
} |
|||
|
|||
switch (key) { |
|||
case KEY_LEFT: |
|||
case TAB: |
|||
case KEY_RIGHT: |
|||
button = ((key == KEY_LEFT ? --button : ++button) < 0) |
|||
? 2 : (button > 2 ? 0 : button); |
|||
|
|||
print_buttons(dialog, height, width, button); |
|||
wrefresh (menu); |
|||
break; |
|||
case ' ': |
|||
case 's': |
|||
case 'y': |
|||
case 'n': |
|||
case 'm': |
|||
/* save scroll info */ |
|||
if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) { |
|||
fprintf(f,"%d\n",scroll); |
|||
fclose(f); |
|||
} |
|||
delwin (dialog); |
|||
fprintf(stderr, "%s\n", items[(scroll + choice) * 2]); |
|||
switch (key) { |
|||
case 's': return 3; |
|||
case 'y': return 3; |
|||
case 'n': return 4; |
|||
case 'm': return 5; |
|||
case ' ': return 6; |
|||
} |
|||
return 0; |
|||
case 'h': |
|||
case '?': |
|||
button = 2; |
|||
case '\n': |
|||
delwin (dialog); |
|||
if (button == 2) |
|||
fprintf(stderr, "%s \"%s\"\n", |
|||
items[(scroll + choice) * 2], |
|||
items[(scroll + choice) * 2 + 1] + |
|||
first_alpha(items[(scroll + choice) * 2 + 1],"")); |
|||
else |
|||
fprintf(stderr, "%s\n", items[(scroll + choice) * 2]); |
|||
|
|||
remove("lxdialog.scrltmp"); |
|||
return button; |
|||
case 'e': |
|||
case 'x': |
|||
key = ESC; |
|||
case ESC: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
delwin (dialog); |
|||
remove("lxdialog.scrltmp"); |
|||
return -1; /* ESC pressed */ |
|||
} |
@ -0,0 +1,85 @@ |
|||
/*
|
|||
* msgbox.c -- implements the message box and info box |
|||
* |
|||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |
|||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) |
|||
* |
|||
* 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 (at your option) 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. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|||
*/ |
|||
|
|||
#include "dialog.h" |
|||
|
|||
/*
|
|||
* Display a message box. Program will pause and display an "OK" button |
|||
* if the parameter 'pause' is non-zero. |
|||
*/ |
|||
int |
|||
dialog_msgbox (const char *title, const char *prompt, int height, int width, |
|||
int pause) |
|||
{ |
|||
int i, x, y, key = 0; |
|||
WINDOW *dialog; |
|||
|
|||
/* center dialog box on screen */ |
|||
x = (COLS - width) / 2; |
|||
y = (LINES - height) / 2; |
|||
|
|||
draw_shadow (stdscr, y, x, height, width); |
|||
|
|||
dialog = newwin (height, width, y, x); |
|||
keypad (dialog, TRUE); |
|||
|
|||
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); |
|||
|
|||
if (title != NULL && strlen(title) >= width-2 ) { |
|||
/* truncate long title -- mec */ |
|||
char * title2 = malloc(width-2+1); |
|||
memcpy( title2, title, width-2 ); |
|||
title2[width-2] = '\0'; |
|||
title = title2; |
|||
} |
|||
|
|||
if (title != NULL) { |
|||
wattrset (dialog, title_attr); |
|||
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); |
|||
waddstr (dialog, (char *)title); |
|||
waddch (dialog, ' '); |
|||
} |
|||
wattrset (dialog, dialog_attr); |
|||
print_autowrap (dialog, prompt, width - 2, 1, 2); |
|||
|
|||
if (pause) { |
|||
wattrset (dialog, border_attr); |
|||
mvwaddch (dialog, height - 3, 0, ACS_LTEE); |
|||
for (i = 0; i < width - 2; i++) |
|||
waddch (dialog, ACS_HLINE); |
|||
wattrset (dialog, dialog_attr); |
|||
waddch (dialog, ACS_RTEE); |
|||
|
|||
print_button (dialog, " Ok ", |
|||
height - 2, width / 2 - 4, TRUE); |
|||
|
|||
wrefresh (dialog); |
|||
while (key != ESC && key != '\n' && key != ' ' && |
|||
key != 'O' && key != 'o' && key != 'X' && key != 'x') |
|||
key = wgetch (dialog); |
|||
} else { |
|||
key = '\n'; |
|||
wrefresh (dialog); |
|||
} |
|||
|
|||
delwin (dialog); |
|||
return key == ESC ? -1 : 0; |
|||
} |
@ -0,0 +1,556 @@ |
|||
/*
|
|||
* textbox.c -- implements the text box |
|||
* |
|||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |
|||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) |
|||
* |
|||
* 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 (at your option) 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. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|||
*/ |
|||
|
|||
#include "dialog.h" |
|||
|
|||
static void back_lines (int n); |
|||
static void print_page (WINDOW * win, int height, int width); |
|||
static void print_line (WINDOW * win, int row, int width); |
|||
static char *get_line (void); |
|||
static void print_position (WINDOW * win, int height, int width); |
|||
|
|||
static int hscroll = 0, fd, file_size, bytes_read; |
|||
static int begin_reached = 1, end_reached = 0, page_length; |
|||
static char *buf, *page; |
|||
|
|||
/*
|
|||
* Display text from a file in a dialog box. |
|||
*/ |
|||
int |
|||
dialog_textbox (const char *title, const char *file, int height, int width) |
|||
{ |
|||
int i, x, y, cur_x, cur_y, fpos, key = 0; |
|||
int passed_end; |
|||
char search_term[MAX_LEN + 1]; |
|||
WINDOW *dialog, *text; |
|||
|
|||
search_term[0] = '\0'; /* no search term entered yet */ |
|||
|
|||
/* Open input file for reading */ |
|||
if ((fd = open (file, O_RDONLY)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, |
|||
"\nCan't open input file in dialog_textbox().\n"); |
|||
exit (-1); |
|||
} |
|||
/* Get file size. Actually, 'file_size' is the real file size - 1,
|
|||
since it's only the last byte offset from the beginning */ |
|||
if ((file_size = lseek (fd, 0, SEEK_END)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError getting file size in dialog_textbox().\n"); |
|||
exit (-1); |
|||
} |
|||
/* Restore file pointer to beginning of file after getting file size */ |
|||
if (lseek (fd, 0, SEEK_SET) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n"); |
|||
exit (-1); |
|||
} |
|||
/* Allocate space for read buffer */ |
|||
if ((buf = malloc (BUF_SIZE + 1)) == NULL) { |
|||
endwin (); |
|||
fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n"); |
|||
exit (-1); |
|||
} |
|||
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError reading file in dialog_textbox().\n"); |
|||
exit (-1); |
|||
} |
|||
buf[bytes_read] = '\0'; /* mark end of valid data */ |
|||
page = buf; /* page is pointer to start of page to be displayed */ |
|||
|
|||
/* center dialog box on screen */ |
|||
x = (COLS - width) / 2; |
|||
y = (LINES - height) / 2; |
|||
|
|||
|
|||
draw_shadow (stdscr, y, x, height, width); |
|||
|
|||
dialog = newwin (height, width, y, x); |
|||
keypad (dialog, TRUE); |
|||
|
|||
/* Create window for text region, used for scrolling text */ |
|||
text = subwin (dialog, height - 4, width - 2, y + 1, x + 1); |
|||
wattrset (text, dialog_attr); |
|||
wbkgdset (text, dialog_attr & A_COLOR); |
|||
|
|||
keypad (text, TRUE); |
|||
|
|||
/* register the new window, along with its borders */ |
|||
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); |
|||
|
|||
wattrset (dialog, border_attr); |
|||
mvwaddch (dialog, height-3, 0, ACS_LTEE); |
|||
for (i = 0; i < width - 2; i++) |
|||
waddch (dialog, ACS_HLINE); |
|||
wattrset (dialog, dialog_attr); |
|||
wbkgdset (dialog, dialog_attr & A_COLOR); |
|||
waddch (dialog, ACS_RTEE); |
|||
|
|||
if (title != NULL && strlen(title) >= width-2 ) { |
|||
/* truncate long title -- mec */ |
|||
char * title2 = malloc(width-2+1); |
|||
memcpy( title2, title, width-2 ); |
|||
title2[width-2] = '\0'; |
|||
title = title2; |
|||
} |
|||
|
|||
if (title != NULL) { |
|||
wattrset (dialog, title_attr); |
|||
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); |
|||
waddstr (dialog, (char *)title); |
|||
waddch (dialog, ' '); |
|||
} |
|||
print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE); |
|||
wnoutrefresh (dialog); |
|||
getyx (dialog, cur_y, cur_x); /* Save cursor position */ |
|||
|
|||
/* Print first page of text */ |
|||
attr_clear (text, height - 4, width - 2, dialog_attr); |
|||
print_page (text, height - 4, width - 2); |
|||
print_position (dialog, height, width); |
|||
wmove (dialog, cur_y, cur_x); /* Restore cursor position */ |
|||
wrefresh (dialog); |
|||
|
|||
while ((key != ESC) && (key != '\n')) { |
|||
key = wgetch (dialog); |
|||
switch (key) { |
|||
case 'E': /* Exit */ |
|||
case 'e': |
|||
case 'X': |
|||
case 'x': |
|||
delwin (dialog); |
|||
free (buf); |
|||
close (fd); |
|||
return 0; |
|||
case 'g': /* First page */ |
|||
case KEY_HOME: |
|||
if (!begin_reached) { |
|||
begin_reached = 1; |
|||
/* First page not in buffer? */ |
|||
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, |
|||
"\nError moving file pointer in dialog_textbox().\n"); |
|||
exit (-1); |
|||
} |
|||
if (fpos > bytes_read) { /* Yes, we have to read it in */ |
|||
if (lseek (fd, 0, SEEK_SET) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError moving file pointer in " |
|||
"dialog_textbox().\n"); |
|||
exit (-1); |
|||
} |
|||
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, |
|||
"\nError reading file in dialog_textbox().\n"); |
|||
exit (-1); |
|||
} |
|||
buf[bytes_read] = '\0'; |
|||
} |
|||
page = buf; |
|||
print_page (text, height - 4, width - 2); |
|||
print_position (dialog, height, width); |
|||
wmove (dialog, cur_y, cur_x); /* Restore cursor position */ |
|||
wrefresh (dialog); |
|||
} |
|||
break; |
|||
case 'G': /* Last page */ |
|||
case KEY_END: |
|||
|
|||
end_reached = 1; |
|||
/* Last page not in buffer? */ |
|||
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, |
|||
"\nError moving file pointer in dialog_textbox().\n"); |
|||
exit (-1); |
|||
} |
|||
if (fpos < file_size) { /* Yes, we have to read it in */ |
|||
if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, |
|||
"\nError moving file pointer in dialog_textbox().\n"); |
|||
exit (-1); |
|||
} |
|||
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, |
|||
"\nError reading file in dialog_textbox().\n"); |
|||
exit (-1); |
|||
} |
|||
buf[bytes_read] = '\0'; |
|||
} |
|||
page = buf + bytes_read; |
|||
back_lines (height - 4); |
|||
print_page (text, height - 4, width - 2); |
|||
print_position (dialog, height, width); |
|||
wmove (dialog, cur_y, cur_x); /* Restore cursor position */ |
|||
wrefresh (dialog); |
|||
break; |
|||
case 'K': /* Previous line */ |
|||
case 'k': |
|||
case KEY_UP: |
|||
if (!begin_reached) { |
|||
back_lines (page_length + 1); |
|||
|
|||
/* We don't call print_page() here but use scrolling to ensure
|
|||
faster screen update. However, 'end_reached' and |
|||
'page_length' should still be updated, and 'page' should |
|||
point to start of next page. This is done by calling |
|||
get_line() in the following 'for' loop. */ |
|||
scrollok (text, TRUE); |
|||
wscrl (text, -1); /* Scroll text region down one line */ |
|||
scrollok (text, FALSE); |
|||
page_length = 0; |
|||
passed_end = 0; |
|||
for (i = 0; i < height - 4; i++) { |
|||
if (!i) { |
|||
/* print first line of page */ |
|||
print_line (text, 0, width - 2); |
|||
wnoutrefresh (text); |
|||
} else |
|||
/* Called to update 'end_reached' and 'page' */ |
|||
get_line (); |
|||
if (!passed_end) |
|||
page_length++; |
|||
if (end_reached && !passed_end) |
|||
passed_end = 1; |
|||
} |
|||
|
|||
print_position (dialog, height, width); |
|||
wmove (dialog, cur_y, cur_x); /* Restore cursor position */ |
|||
wrefresh (dialog); |
|||
} |
|||
break; |
|||
case 'B': /* Previous page */ |
|||
case 'b': |
|||
case KEY_PPAGE: |
|||
if (begin_reached) |
|||
break; |
|||
back_lines (page_length + height - 4); |
|||
print_page (text, height - 4, width - 2); |
|||
print_position (dialog, height, width); |
|||
wmove (dialog, cur_y, cur_x); |
|||
wrefresh (dialog); |
|||
break; |
|||
case 'J': /* Next line */ |
|||
case 'j': |
|||
case KEY_DOWN: |
|||
if (!end_reached) { |
|||
begin_reached = 0; |
|||
scrollok (text, TRUE); |
|||
scroll (text); /* Scroll text region up one line */ |
|||
scrollok (text, FALSE); |
|||
print_line (text, height - 5, width - 2); |
|||
wnoutrefresh (text); |
|||
print_position (dialog, height, width); |
|||
wmove (dialog, cur_y, cur_x); /* Restore cursor position */ |
|||
wrefresh (dialog); |
|||
} |
|||
break; |
|||
case KEY_NPAGE: /* Next page */ |
|||
case ' ': |
|||
if (end_reached) |
|||
break; |
|||
|
|||
begin_reached = 0; |
|||
print_page (text, height - 4, width - 2); |
|||
print_position (dialog, height, width); |
|||
wmove (dialog, cur_y, cur_x); |
|||
wrefresh (dialog); |
|||
break; |
|||
case '0': /* Beginning of line */ |
|||
case 'H': /* Scroll left */ |
|||
case 'h': |
|||
case KEY_LEFT: |
|||
if (hscroll <= 0) |
|||
break; |
|||
|
|||
if (key == '0') |
|||
hscroll = 0; |
|||
else |
|||
hscroll--; |
|||
/* Reprint current page to scroll horizontally */ |
|||
back_lines (page_length); |
|||
print_page (text, height - 4, width - 2); |
|||
wmove (dialog, cur_y, cur_x); |
|||
wrefresh (dialog); |
|||
break; |
|||
case 'L': /* Scroll right */ |
|||
case 'l': |
|||
case KEY_RIGHT: |
|||
if (hscroll >= MAX_LEN) |
|||
break; |
|||
hscroll++; |
|||
/* Reprint current page to scroll horizontally */ |
|||
back_lines (page_length); |
|||
print_page (text, height - 4, width - 2); |
|||
wmove (dialog, cur_y, cur_x); |
|||
wrefresh (dialog); |
|||
break; |
|||
case ESC: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
delwin (dialog); |
|||
free (buf); |
|||
close (fd); |
|||
return -1; /* ESC pressed */ |
|||
} |
|||
|
|||
/*
|
|||
* Go back 'n' lines in text file. Called by dialog_textbox(). |
|||
* 'page' will be updated to point to the desired line in 'buf'. |
|||
*/ |
|||
static void |
|||
back_lines (int n) |
|||
{ |
|||
int i, fpos; |
|||
|
|||
begin_reached = 0; |
|||
/* We have to distinguish between end_reached and !end_reached
|
|||
since at end of file, the line is not ended by a '\n'. |
|||
The code inside 'if' basically does a '--page' to move one |
|||
character backward so as to skip '\n' of the previous line */ |
|||
if (!end_reached) { |
|||
/* Either beginning of buffer or beginning of file reached? */ |
|||
if (page == buf) { |
|||
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError moving file pointer in " |
|||
"back_lines().\n"); |
|||
exit (-1); |
|||
} |
|||
if (fpos > bytes_read) { /* Not beginning of file yet */ |
|||
/* We've reached beginning of buffer, but not beginning of
|
|||
file yet, so read previous part of file into buffer. |
|||
Note that we only move backward for BUF_SIZE/2 bytes, |
|||
but not BUF_SIZE bytes to avoid re-reading again in |
|||
print_page() later */ |
|||
/* Really possible to move backward BUF_SIZE/2 bytes? */ |
|||
if (fpos < BUF_SIZE / 2 + bytes_read) { |
|||
/* No, move less then */ |
|||
if (lseek (fd, 0, SEEK_SET) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError moving file pointer in " |
|||
"back_lines().\n"); |
|||
exit (-1); |
|||
} |
|||
page = buf + fpos - bytes_read; |
|||
} else { /* Move backward BUF_SIZE/2 bytes */ |
|||
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) |
|||
== -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError moving file pointer " |
|||
"in back_lines().\n"); |
|||
exit (-1); |
|||
} |
|||
page = buf + BUF_SIZE / 2; |
|||
} |
|||
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError reading file in back_lines().\n"); |
|||
exit (-1); |
|||
} |
|||
buf[bytes_read] = '\0'; |
|||
} else { /* Beginning of file reached */ |
|||
begin_reached = 1; |
|||
return; |
|||
} |
|||
} |
|||
if (*(--page) != '\n') { /* '--page' here */ |
|||
/* Something's wrong... */ |
|||
endwin (); |
|||
fprintf (stderr, "\nInternal error in back_lines().\n"); |
|||
exit (-1); |
|||
} |
|||
} |
|||
/* Go back 'n' lines */ |
|||
for (i = 0; i < n; i++) |
|||
do { |
|||
if (page == buf) { |
|||
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, |
|||
"\nError moving file pointer in back_lines().\n"); |
|||
exit (-1); |
|||
} |
|||
if (fpos > bytes_read) { |
|||
/* Really possible to move backward BUF_SIZE/2 bytes? */ |
|||
if (fpos < BUF_SIZE / 2 + bytes_read) { |
|||
/* No, move less then */ |
|||
if (lseek (fd, 0, SEEK_SET) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError moving file pointer " |
|||
"in back_lines().\n"); |
|||
exit (-1); |
|||
} |
|||
page = buf + fpos - bytes_read; |
|||
} else { /* Move backward BUF_SIZE/2 bytes */ |
|||
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), |
|||
SEEK_CUR) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError moving file pointer" |
|||
" in back_lines().\n"); |
|||
exit (-1); |
|||
} |
|||
page = buf + BUF_SIZE / 2; |
|||
} |
|||
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError reading file in " |
|||
"back_lines().\n"); |
|||
exit (-1); |
|||
} |
|||
buf[bytes_read] = '\0'; |
|||
} else { /* Beginning of file reached */ |
|||
begin_reached = 1; |
|||
return; |
|||
} |
|||
} |
|||
} while (*(--page) != '\n'); |
|||
page++; |
|||
} |
|||
|
|||
/*
|
|||
* Print a new page of text. Called by dialog_textbox(). |
|||
*/ |
|||
static void |
|||
print_page (WINDOW * win, int height, int width) |
|||
{ |
|||
int i, passed_end = 0; |
|||
|
|||
page_length = 0; |
|||
for (i = 0; i < height; i++) { |
|||
print_line (win, i, width); |
|||
if (!passed_end) |
|||
page_length++; |
|||
if (end_reached && !passed_end) |
|||
passed_end = 1; |
|||
} |
|||
wnoutrefresh (win); |
|||
} |
|||
|
|||
/*
|
|||
* Print a new line of text. Called by dialog_textbox() and print_page(). |
|||
*/ |
|||
static void |
|||
print_line (WINDOW * win, int row, int width) |
|||
{ |
|||
int y, x; |
|||
char *line; |
|||
|
|||
line = get_line (); |
|||
line += MIN (strlen (line), hscroll); /* Scroll horizontally */ |
|||
wmove (win, row, 0); /* move cursor to correct line */ |
|||
waddch (win, ' '); |
|||
waddnstr (win, line, MIN (strlen (line), width - 2)); |
|||
|
|||
getyx (win, y, x); |
|||
/* Clear 'residue' of previous line */ |
|||
#if OLD_NCURSES |
|||
{ |
|||
int i; |
|||
for (i = 0; i < width - x; i++) |
|||
waddch (win, ' '); |
|||
} |
|||
#else |
|||
wclrtoeol(win); |
|||
#endif |
|||
} |
|||
|
|||
/*
|
|||
* Return current line of text. Called by dialog_textbox() and print_line(). |
|||
* 'page' should point to start of current line before calling, and will be |
|||
* updated to point to start of next line. |
|||
*/ |
|||
static char * |
|||
get_line (void) |
|||
{ |
|||
int i = 0, fpos; |
|||
static char line[MAX_LEN + 1]; |
|||
|
|||
end_reached = 0; |
|||
while (*page != '\n') { |
|||
if (*page == '\0') { |
|||
/* Either end of file or end of buffer reached */ |
|||
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError moving file pointer in " |
|||
"get_line().\n"); |
|||
exit (-1); |
|||
} |
|||
if (fpos < file_size) { /* Not end of file yet */ |
|||
/* We've reached end of buffer, but not end of file yet,
|
|||
so read next part of file into buffer */ |
|||
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError reading file in get_line().\n"); |
|||
exit (-1); |
|||
} |
|||
buf[bytes_read] = '\0'; |
|||
page = buf; |
|||
} else { |
|||
if (!end_reached) |
|||
end_reached = 1; |
|||
break; |
|||
} |
|||
} else if (i < MAX_LEN) |
|||
line[i++] = *(page++); |
|||
else { |
|||
/* Truncate lines longer than MAX_LEN characters */ |
|||
if (i == MAX_LEN) |
|||
line[i++] = '\0'; |
|||
page++; |
|||
} |
|||
} |
|||
if (i <= MAX_LEN) |
|||
line[i] = '\0'; |
|||
if (!end_reached) |
|||
page++; /* move pass '\n' */ |
|||
|
|||
return line; |
|||
} |
|||
|
|||
/*
|
|||
* Print current position |
|||
*/ |
|||
static void |
|||
print_position (WINDOW * win, int height, int width) |
|||
{ |
|||
int fpos, percent; |
|||
|
|||
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { |
|||
endwin (); |
|||
fprintf (stderr, "\nError moving file pointer in print_position().\n"); |
|||
exit (-1); |
|||
} |
|||
wattrset (win, position_indicator_attr); |
|||
wbkgdset (win, position_indicator_attr & A_COLOR); |
|||
percent = !file_size ? |
|||
100 : ((fpos - bytes_read + page - buf) * 100) / file_size; |
|||
wmove (win, height - 3, width - 9); |
|||
wprintw (win, "(%3d%%)", percent); |
|||
} |
@ -0,0 +1,359 @@ |
|||
/*
|
|||
* util.c |
|||
* |
|||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |
|||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) |
|||
* |
|||
* 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 (at your option) 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. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|||
*/ |
|||
|
|||
#include "dialog.h" |
|||
|
|||
|
|||
/* use colors by default? */ |
|||
bool use_colors = 1; |
|||
|
|||
const char *backtitle = NULL; |
|||
|
|||
const char *dialog_result; |
|||
|
|||
/*
|
|||
* Attribute values, default is for mono display |
|||
*/ |
|||
chtype attributes[] = |
|||
{ |
|||
A_NORMAL, /* screen_attr */ |
|||
A_NORMAL, /* shadow_attr */ |
|||
A_NORMAL, /* dialog_attr */ |
|||
A_BOLD, /* title_attr */ |
|||
A_NORMAL, /* border_attr */ |
|||
A_REVERSE, /* button_active_attr */ |
|||
A_DIM, /* button_inactive_attr */ |
|||
A_REVERSE, /* button_key_active_attr */ |
|||
A_BOLD, /* button_key_inactive_attr */ |
|||
A_REVERSE, /* button_label_active_attr */ |
|||
A_NORMAL, /* button_label_inactive_attr */ |
|||
A_NORMAL, /* inputbox_attr */ |
|||
A_NORMAL, /* inputbox_border_attr */ |
|||
A_NORMAL, /* searchbox_attr */ |
|||
A_BOLD, /* searchbox_title_attr */ |
|||
A_NORMAL, /* searchbox_border_attr */ |
|||
A_BOLD, /* position_indicator_attr */ |
|||
A_NORMAL, /* menubox_attr */ |
|||
A_NORMAL, /* menubox_border_attr */ |
|||
A_NORMAL, /* item_attr */ |
|||
A_REVERSE, /* item_selected_attr */ |
|||
A_BOLD, /* tag_attr */ |
|||
A_REVERSE, /* tag_selected_attr */ |
|||
A_BOLD, /* tag_key_attr */ |
|||
A_REVERSE, /* tag_key_selected_attr */ |
|||
A_BOLD, /* check_attr */ |
|||
A_REVERSE, /* check_selected_attr */ |
|||
A_BOLD, /* uarrow_attr */ |
|||
A_BOLD /* darrow_attr */ |
|||
}; |
|||
|
|||
|
|||
#include "colors.h" |
|||
|
|||
/*
|
|||
* Table of color values |
|||
*/ |
|||
int color_table[][3] = |
|||
{ |
|||
{SCREEN_FG, SCREEN_BG, SCREEN_HL}, |
|||
{SHADOW_FG, SHADOW_BG, SHADOW_HL}, |
|||
{DIALOG_FG, DIALOG_BG, DIALOG_HL}, |
|||
{TITLE_FG, TITLE_BG, TITLE_HL}, |
|||
{BORDER_FG, BORDER_BG, BORDER_HL}, |
|||
{BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL}, |
|||
{BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL}, |
|||
{BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL}, |
|||
{BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL}, |
|||
{BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL}, |
|||
{BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG, |
|||
BUTTON_LABEL_INACTIVE_HL}, |
|||
{INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL}, |
|||
{INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL}, |
|||
{SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL}, |
|||
{SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL}, |
|||
{SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL}, |
|||
{POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL}, |
|||
{MENUBOX_FG, MENUBOX_BG, MENUBOX_HL}, |
|||
{MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL}, |
|||
{ITEM_FG, ITEM_BG, ITEM_HL}, |
|||
{ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL}, |
|||
{TAG_FG, TAG_BG, TAG_HL}, |
|||
{TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL}, |
|||
{TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL}, |
|||
{TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL}, |
|||
{CHECK_FG, CHECK_BG, CHECK_HL}, |
|||
{CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL}, |
|||
{UARROW_FG, UARROW_BG, UARROW_HL}, |
|||
{DARROW_FG, DARROW_BG, DARROW_HL}, |
|||
}; /* color_table */ |
|||
|
|||
/*
|
|||
* Set window to attribute 'attr' |
|||
*/ |
|||
void |
|||
attr_clear (WINDOW * win, int height, int width, chtype attr) |
|||
{ |
|||
int i, j; |
|||
|
|||
wattrset (win, attr); |
|||
for (i = 0; i < height; i++) { |
|||
wmove (win, i, 0); |
|||
for (j = 0; j < width; j++) |
|||
waddch (win, ' '); |
|||
} |
|||
touchwin (win); |
|||
} |
|||
|
|||
void dialog_clear (void) |
|||
{ |
|||
attr_clear (stdscr, LINES, COLS, screen_attr); |
|||
/* Display background title if it exists ... - SLH */ |
|||
if (backtitle != NULL) { |
|||
int i; |
|||
|
|||
wattrset (stdscr, screen_attr); |
|||
mvwaddstr (stdscr, 0, 1, (char *)backtitle); |
|||
wmove (stdscr, 1, 1); |
|||
for (i = 1; i < COLS - 1; i++) |
|||
waddch (stdscr, ACS_HLINE); |
|||
} |
|||
wnoutrefresh (stdscr); |
|||
} |
|||
|
|||
/*
|
|||
* Do some initialization for dialog |
|||
*/ |
|||
void |
|||
init_dialog (void) |
|||
{ |
|||
initscr (); /* Init curses */ |
|||
keypad (stdscr, TRUE); |
|||
cbreak (); |
|||
noecho (); |
|||
|
|||
|
|||
if (use_colors) /* Set up colors */ |
|||
color_setup (); |
|||
|
|||
|
|||
dialog_clear (); |
|||
} |
|||
|
|||
/*
|
|||
* Setup for color display |
|||
*/ |
|||
void |
|||
color_setup (void) |
|||
{ |
|||
int i; |
|||
|
|||
if (has_colors ()) { /* Terminal supports color? */ |
|||
start_color (); |
|||
|
|||
/* Initialize color pairs */ |
|||
for (i = 0; i < ATTRIBUTE_COUNT; i++) |
|||
init_pair (i + 1, color_table[i][0], color_table[i][1]); |
|||
|
|||
/* Setup color attributes */ |
|||
for (i = 0; i < ATTRIBUTE_COUNT; i++) |
|||
attributes[i] = C_ATTR (color_table[i][2], i + 1); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* End using dialog functions. |
|||
*/ |
|||
void |
|||
end_dialog (void) |
|||
{ |
|||
endwin (); |
|||
} |
|||
|
|||
|
|||
/*
|
|||
* Print a string of text in a window, automatically wrap around to the |
|||
* next line if the string is too long to fit on one line. Newline |
|||
* characters '\n' are replaced by spaces. We start on a new line |
|||
* if there is no room for at least 4 nonblanks following a double-space. |
|||
*/ |
|||
void |
|||
print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x) |
|||
{ |
|||
int newl, cur_x, cur_y; |
|||
int i, prompt_len, room, wlen; |
|||
char tempstr[MAX_LEN + 1], *word, *sp, *sp2; |
|||
|
|||
strcpy (tempstr, prompt); |
|||
|
|||
prompt_len = strlen(tempstr); |
|||
|
|||
/*
|
|||
* Remove newlines |
|||
*/ |
|||
for(i=0; i<prompt_len; i++) { |
|||
if(tempstr[i] == '\n') tempstr[i] = ' '; |
|||
} |
|||
|
|||
if (prompt_len <= width - x * 2) { /* If prompt is short */ |
|||
wmove (win, y, (width - prompt_len) / 2); |
|||
waddstr (win, tempstr); |
|||
} else { |
|||
cur_x = x; |
|||
cur_y = y; |
|||
newl = 1; |
|||
word = tempstr; |
|||
while (word && *word) { |
|||
sp = index(word, ' '); |
|||
if (sp) |
|||
*sp++ = 0; |
|||
|
|||
/* Wrap to next line if either the word does not fit,
|
|||
or it is the first word of a new sentence, and it is |
|||
short, and the next word does not fit. */ |
|||
room = width - cur_x; |
|||
wlen = strlen(word); |
|||
if (wlen > room || |
|||
(newl && wlen < 4 && sp && wlen+1+strlen(sp) > room |
|||
&& (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) { |
|||
cur_y++; |
|||
cur_x = x; |
|||
} |
|||
wmove (win, cur_y, cur_x); |
|||
waddstr (win, word); |
|||
getyx (win, cur_y, cur_x); |
|||
cur_x++; |
|||
if (sp && *sp == ' ') { |
|||
cur_x++; /* double space */ |
|||
while (*++sp == ' '); |
|||
newl = 1; |
|||
} else |
|||
newl = 0; |
|||
word = sp; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Print a button |
|||
*/ |
|||
void |
|||
print_button (WINDOW * win, const char *label, int y, int x, int selected) |
|||
{ |
|||
int i, temp; |
|||
|
|||
wmove (win, y, x); |
|||
wattrset (win, selected ? button_active_attr : button_inactive_attr); |
|||
waddstr (win, "<"); |
|||
temp = strspn (label, " "); |
|||
label += temp; |
|||
wattrset (win, selected ? button_label_active_attr |
|||
: button_label_inactive_attr); |
|||
for (i = 0; i < temp; i++) |
|||
waddch (win, ' '); |
|||
wattrset (win, selected ? button_key_active_attr |
|||
: button_key_inactive_attr); |
|||
waddch (win, label[0]); |
|||
wattrset (win, selected ? button_label_active_attr |
|||
: button_label_inactive_attr); |
|||
waddstr (win, (char *)label + 1); |
|||
wattrset (win, selected ? button_active_attr : button_inactive_attr); |
|||
waddstr (win, ">"); |
|||
wmove (win, y, x + temp + 1); |
|||
} |
|||
|
|||
/*
|
|||
* Draw a rectangular box with line drawing characters |
|||
*/ |
|||
void |
|||
draw_box (WINDOW * win, int y, int x, int height, int width, |
|||
chtype box, chtype border) |
|||
{ |
|||
int i, j; |
|||
|
|||
wattrset (win, 0); |
|||
for (i = 0; i < height; i++) { |
|||
wmove (win, y + i, x); |
|||
for (j = 0; j < width; j++) |
|||
if (!i && !j) |
|||
waddch (win, border | ACS_ULCORNER); |
|||
else if (i == height - 1 && !j) |
|||
waddch (win, border | ACS_LLCORNER); |
|||
else if (!i && j == width - 1) |
|||
waddch (win, box | ACS_URCORNER); |
|||
else if (i == height - 1 && j == width - 1) |
|||
waddch (win, box | ACS_LRCORNER); |
|||
else if (!i) |
|||
waddch (win, border | ACS_HLINE); |
|||
else if (i == height - 1) |
|||
waddch (win, box | ACS_HLINE); |
|||
else if (!j) |
|||
waddch (win, border | ACS_VLINE); |
|||
else if (j == width - 1) |
|||
waddch (win, box | ACS_VLINE); |
|||
else |
|||
waddch (win, box | ' '); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Draw shadows along the right and bottom edge to give a more 3D look |
|||
* to the boxes |
|||
*/ |
|||
void |
|||
draw_shadow (WINDOW * win, int y, int x, int height, int width) |
|||
{ |
|||
int i; |
|||
|
|||
if (has_colors ()) { /* Whether terminal supports color? */ |
|||
wattrset (win, shadow_attr); |
|||
wmove (win, y + height, x + 2); |
|||
for (i = 0; i < width; i++) |
|||
waddch (win, winch (win) & A_CHARTEXT); |
|||
for (i = y + 1; i < y + height + 1; i++) { |
|||
wmove (win, i, x + width); |
|||
waddch (win, winch (win) & A_CHARTEXT); |
|||
waddch (win, winch (win) & A_CHARTEXT); |
|||
} |
|||
wnoutrefresh (win); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Return the position of the first alphabetic character in a string. |
|||
*/ |
|||
int |
|||
first_alpha(const char *string, const char *exempt) |
|||
{ |
|||
int i, in_paren=0, c; |
|||
|
|||
for (i = 0; i < strlen(string); i++) { |
|||
c = tolower(string[i]); |
|||
|
|||
if (strchr("<[(", c)) ++in_paren; |
|||
if (strchr(">])", c)) --in_paren; |
|||
|
|||
if ((! in_paren) && isalpha(c) && |
|||
strchr(exempt, c) == 0) |
|||
return i; |
|||
} |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,118 @@ |
|||
/*
|
|||
* yesno.c -- implements the yes/no box |
|||
* |
|||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |
|||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) |
|||
* |
|||
* 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 (at your option) 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. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|||
*/ |
|||
|
|||
#include "dialog.h" |
|||
|
|||
/*
|
|||
* Display termination buttons |
|||
*/ |
|||
static void |
|||
print_buttons(WINDOW *dialog, int height, int width, int selected) |
|||
{ |
|||
int x = width / 2 - 10; |
|||
int y = height - 2; |
|||
|
|||
print_button (dialog, " Yes ", y, x, selected == 0); |
|||
print_button (dialog, " No ", y, x + 13, selected == 1); |
|||
|
|||
wmove(dialog, y, x+1 + 13*selected ); |
|||
wrefresh (dialog); |
|||
} |
|||
|
|||
/*
|
|||
* Display a dialog box with two buttons - Yes and No |
|||
*/ |
|||
int |
|||
dialog_yesno (const char *title, const char *prompt, int height, int width) |
|||
{ |
|||
int i, x, y, key = 0, button = 0; |
|||
WINDOW *dialog; |
|||
|
|||
/* center dialog box on screen */ |
|||
x = (COLS - width) / 2; |
|||
y = (LINES - height) / 2; |
|||
|
|||
draw_shadow (stdscr, y, x, height, width); |
|||
|
|||
dialog = newwin (height, width, y, x); |
|||
keypad (dialog, TRUE); |
|||
|
|||
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); |
|||
wattrset (dialog, border_attr); |
|||
mvwaddch (dialog, height-3, 0, ACS_LTEE); |
|||
for (i = 0; i < width - 2; i++) |
|||
waddch (dialog, ACS_HLINE); |
|||
wattrset (dialog, dialog_attr); |
|||
waddch (dialog, ACS_RTEE); |
|||
|
|||
if (title != NULL && strlen(title) >= width-2 ) { |
|||
/* truncate long title -- mec */ |
|||
char * title2 = malloc(width-2+1); |
|||
memcpy( title2, title, width-2 ); |
|||
title2[width-2] = '\0'; |
|||
title = title2; |
|||
} |
|||
|
|||
if (title != NULL) { |
|||
wattrset (dialog, title_attr); |
|||
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); |
|||
waddstr (dialog, (char *)title); |
|||
waddch (dialog, ' '); |
|||
} |
|||
|
|||
wattrset (dialog, dialog_attr); |
|||
print_autowrap (dialog, prompt, width - 2, 1, 3); |
|||
|
|||
print_buttons(dialog, height, width, 0); |
|||
|
|||
while (key != ESC) { |
|||
key = wgetch (dialog); |
|||
switch (key) { |
|||
case 'Y': |
|||
case 'y': |
|||
delwin (dialog); |
|||
return 0; |
|||
case 'N': |
|||
case 'n': |
|||
delwin (dialog); |
|||
return 1; |
|||
|
|||
case TAB: |
|||
case KEY_LEFT: |
|||
case KEY_RIGHT: |
|||
button = ((key == KEY_LEFT ? --button : ++button) < 0) |
|||
? 1 : (button > 1 ? 0 : button); |
|||
|
|||
print_buttons(dialog, height, width, button); |
|||
wrefresh (dialog); |
|||
break; |
|||
case ' ': |
|||
case '\n': |
|||
delwin (dialog); |
|||
return button; |
|||
case ESC: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
delwin (dialog); |
|||
return -1; /* ESC pressed */ |
|||
} |
@ -0,0 +1,13 @@ |
|||
#!/bin/bash |
|||
j=0 |
|||
for i in ".text" ".data" ".bss" |
|||
do |
|||
val[$j]=$(avr-size -A $1 | grep $i | sed -e "s/^$i *//g" | cut -d " " -f1) |
|||
let j=$j+1 |
|||
done |
|||
echo "" |
|||
echo "Program: $(echo ${val[0]}+${val[1]}|bc) bytes" |
|||
echo "(.text + .data)" |
|||
echo "" |
|||
echo "Data: $(echo ${val[2]}+${val[1]}|bc) bytes" |
|||
echo "(.data + .bss)" |
@ -0,0 +1,10 @@ |
|||
TARGET = libscrolltext.a |
|||
TOPDIR = .. |
|||
|
|||
include $(TOPDIR)/defaults.mk |
|||
|
|||
SRC = scrolltext3.c |
|||
|
|||
SRC += $(SCROLLTEXT_FONT).c |
|||
|
|||
include $(TOPDIR)/rules.mk |
@ -0,0 +1,20 @@ |
|||
|
|||
dep_bool_menu "Scrolltext Support" SCROLLTEXT_SUPPORT y |
|||
|
|||
choice 'Scrolltext Font' \ |
|||
'Arial_8 font_arial8 \ |
|||
Small_6 font_small6 \ |
|||
Uni_53 font_uni53' \ |
|||
'Arial_8' SCROLLTEXT_FONT |
|||
|
|||
int "Scrolltest buffer size" SCROLLTEXT_BUFFER_SIZE 128 |
|||
int "Scrolltext default delay" SCROLLTEXT_DELAY 60 |
|||
|
|||
int "Default x speed" SCROLL_X_SPEED 20 |
|||
int "Default y speed" SCROLL_Y_SPEED 20 |
|||
|
|||
string "Default text" SCROLLTEXT_TEXT "</#www.das-labor.org" |
|||
|
|||
|
|||
|
|||
endmenu |
@ -0,0 +1,21 @@ |
|||
#ifndef FONT_H |
|||
#define FONT_H |
|||
#ifdef AVR |
|||
# include <avr/pgmspace.h> |
|||
#else |
|||
# define PROGMEM |
|||
# define pgm_read_byte(B) *(B) |
|||
# define pgm_read_word(B) *(B) |
|||
#endif |
|||
|
|||
typedef struct{ |
|||
unsigned char fontHeight; |
|||
const unsigned int* fontIndex; |
|||
const unsigned char* fontData; |
|||
unsigned char glyph_beg; |
|||
unsigned char glyph_end; |
|||
unsigned char glyph_def; |
|||
unsigned char storebytes; |
|||
} font; |
|||
|
|||
#endif //FONT_H
|
@ -0,0 +1,544 @@ |
|||
#include "font.h" |
|||
|
|||
unsigned int PROGMEM fontIndex_arial8[] = { |
|||
0, /* */ |
|||
2, /* ! */ |
|||
4, /* " */ |
|||
10, /* # */ |
|||
20, /* $ */ |
|||
30, /* % */ |
|||
48, /* & */ |
|||
60, /* ' */ |
|||
62, /* ( */ |
|||
68, /* ) */ |
|||
74, /* * */ |
|||
80, /* + */ |
|||
90, /* , */ |
|||
94, /* - */ |
|||
100, /* . */ |
|||
104, /* / */ |
|||
110, /* 0 */ |
|||
120, /* 1 */ |
|||
126, /* 2 */ |
|||
136, /* 3 */ |
|||
146, /* 4 */ |
|||
156, /* 5 */ |
|||
166, /* 6 */ |
|||
176, /* 7 */ |
|||
186, /* 8 */ |
|||
196, /* 9 */ |
|||
206, /* : */ |
|||
208, /* ; */ |
|||
210, /* < */ |
|||
220, /* = */ |
|||
230, /* > */ |
|||
240, /* ? */ |
|||
250, /* @ */ |
|||
270, /* A */ |
|||
284, /* B */ |
|||
296, /* C */ |
|||
308, /* D */ |
|||
320, /* E */ |
|||
330, /* F */ |
|||
340, /* G */ |
|||
354, /* H */ |
|||
366, /* I */ |
|||
368, /* J */ |
|||
376, /* K */ |
|||
388, /* L */ |
|||
398, /* M */ |
|||
412, /* N */ |
|||
424, /* O */ |
|||
438, /* P */ |
|||
448, /* Q */ |
|||
462, /* R */ |
|||
474, /* S */ |
|||
486, /* T */ |
|||
496, /* U */ |
|||
508, /* V */ |
|||
522, /* W */ |
|||
542, /* X */ |
|||
554, /* Y */ |
|||
568, /* Z */ |
|||
580, /* [ */ |
|||
584, /* \ */ |
|||
590, /* ] */ |
|||
594, /* ^ */ |
|||
604, /* _ */ |
|||
616, /* ` */ |
|||
620, /* a */ |
|||
630, /* b */ |
|||
640, /* c */ |
|||
650, /* d */ |
|||
660, /* e */ |
|||
670, /* f */ |
|||
676, /* g */ |
|||
686, /* h */ |
|||
696, /* i */ |
|||
698, /* j */ |
|||
700, /* k */ |
|||
708, /* l */ |
|||
710, /* m */ |
|||
724, /* n */ |
|||
734, /* o */ |
|||
744, /* p */ |
|||
754, /* q */ |
|||
764, /* r */ |
|||
770, /* s */ |
|||
780, /* t */ |
|||
784, /* u */ |
|||
794, /* v */ |
|||
804, /* w */ |
|||
822, /* x */ |
|||
832, /* y */ |
|||
842, /* z */ |
|||
852, /* { */ |
|||
858, /* | */ |
|||
860, /* } */ |
|||
868, /* ~ */ |
|||
878 |
|||
}; |
|||
|
|||
unsigned char PROGMEM fontData_arial8[] = { |
|||
0x00, 0x00, /* */ |
|||
0xfc, 0x02, /* # ###### */ |
|||
0x1c, 0x00, /* ### */ |
|||
0x00, 0x00, /* */ |
|||
0x1c, 0x00, /* ### */ |
|||
0x90, 0x03, /* ### # */ |
|||
0xf0, 0x00, /* #### */ |
|||
0x9c, 0x03, /* ### ### */ |
|||
0xf0, 0x00, /* #### */ |
|||
0x9c, 0x00, /* # ### */ |
|||
0x18, 0x01, /* # ## */ |
|||
0x24, 0x02, /* # # # */ |
|||
0xfc, 0x07, /* ######### */ |
|||
0x24, 0x02, /* # # # */ |
|||
0xc8, 0x01, /* ### # */ |
|||
0x18, 0x00, /* ## */ |
|||
0x24, 0x00, /* # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x98, 0x01, /* ## ## */ |
|||
0x60, 0x00, /* ## */ |
|||
0x98, 0x01, /* ## ## */ |
|||
0x44, 0x02, /* # # # */ |
|||
0x40, 0x02, /* # # */ |
|||
0x80, 0x01, /* ## */ |
|||
0x80, 0x01, /* ## */ |
|||
0x58, 0x02, /* # # ## */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x64, 0x02, /* # ## # */ |
|||
0x98, 0x01, /* ## ## */ |
|||
0x80, 0x02, /* # # */ |
|||
0x1c, 0x00, /* ### */ |
|||
0xf0, 0x03, /* ###### */ |
|||
0x08, 0x04, /* # # */ |
|||
0x04, 0x08, /* # # */ |
|||
0x04, 0x08, /* # # */ |
|||
0x08, 0x04, /* # # */ |
|||
0xf0, 0x03, /* ###### */ |
|||
0x28, 0x00, /* # # */ |
|||
0x1c, 0x00, /* ### */ |
|||
0x28, 0x00, /* # # */ |
|||
0x40, 0x00, /* # */ |
|||
0x40, 0x00, /* # */ |
|||
0xf0, 0x01, /* ##### */ |
|||
0x40, 0x00, /* # */ |
|||
0x40, 0x00, /* # */ |
|||
0x00, 0x00, /* */ |
|||
0x00, 0x0e, /* ### */ |
|||
0x80, 0x00, /* # */ |
|||
0x80, 0x00, /* # */ |
|||
0x80, 0x00, /* # */ |
|||
0x00, 0x00, /* */ |
|||
0x00, 0x02, /* # */ |
|||
0x00, 0x03, /* ## */ |
|||
0xf0, 0x00, /* #### */ |
|||
0x0c, 0x00, /* ## */ |
|||
0xf8, 0x01, /* ###### */ |
|||
0x04, 0x02, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0xf8, 0x01, /* ###### */ |
|||
0x10, 0x00, /* # */ |
|||
0x08, 0x00, /* # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x08, 0x02, /* # # */ |
|||
0x04, 0x03, /* ## # */ |
|||
0x84, 0x02, /* # # # */ |
|||
0x44, 0x02, /* # # # */ |
|||
0x38, 0x02, /* # ### */ |
|||
0x08, 0x01, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0xd8, 0x01, /* ### ## */ |
|||
0xc0, 0x00, /* ## */ |
|||
0xb0, 0x00, /* # ## */ |
|||
0x88, 0x00, /* # # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x80, 0x00, /* # */ |
|||
0x30, 0x01, /* # ## */ |
|||
0x2c, 0x02, /* # # ## */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0xc4, 0x01, /* ### # */ |
|||
0xf8, 0x01, /* ###### */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0xc8, 0x01, /* ### # */ |
|||
0x04, 0x00, /* # */ |
|||
0x84, 0x03, /* ### # */ |
|||
0x64, 0x00, /* ## # */ |
|||
0x1c, 0x00, /* ### */ |
|||
0x04, 0x00, /* # */ |
|||
0xd8, 0x01, /* ### ## */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0xd8, 0x01, /* ### ## */ |
|||
0x38, 0x01, /* # ### */ |
|||
0x44, 0x02, /* # # # */ |
|||
0x44, 0x02, /* # # # */ |
|||
0x44, 0x02, /* # # # */ |
|||
0xf8, 0x01, /* ###### */ |
|||
0x10, 0x02, /* # # */ |
|||
0x10, 0x0e, /* ### # */ |
|||
0x40, 0x00, /* # */ |
|||
0xa0, 0x00, /* # # */ |
|||
0xa0, 0x00, /* # # */ |
|||
0xa0, 0x00, /* # # */ |
|||
0x10, 0x01, /* # # */ |
|||
0xa0, 0x00, /* # # */ |
|||
0xa0, 0x00, /* # # */ |
|||
0xa0, 0x00, /* # # */ |
|||
0xa0, 0x00, /* # # */ |
|||
0xa0, 0x00, /* # # */ |
|||
0x10, 0x01, /* # # */ |
|||
0xa0, 0x00, /* # # */ |
|||
0xa0, 0x00, /* # # */ |
|||
0xa0, 0x00, /* # # */ |
|||
0x40, 0x00, /* # */ |
|||
0x08, 0x00, /* # */ |
|||
0x04, 0x00, /* # */ |
|||
0xc4, 0x02, /* # ## # */ |
|||
0x24, 0x00, /* # # */ |
|||
0x18, 0x00, /* ## */ |
|||
0xe0, 0x03, /* ##### */ |
|||
0x18, 0x04, /* # ## */ |
|||
0xc8, 0x09, /* # ### # */ |
|||
0x24, 0x0a, /* # # # # */ |
|||
0x14, 0x0a, /* # # # # */ |
|||
0x14, 0x09, /* # # # # */ |
|||
0xe4, 0x0b, /* # ##### # */ |
|||
0x34, 0x0a, /* # # ## # */ |
|||
0x08, 0x05, /* # # # */ |
|||
0xf0, 0x04, /* # #### */ |
|||
0x00, 0x03, /* ## */ |
|||
0xc0, 0x00, /* ## */ |
|||
0xb8, 0x00, /* # ### */ |
|||
0x84, 0x00, /* # # */ |
|||
0xb8, 0x00, /* # ### */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x00, 0x03, /* ## */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0xf8, 0x01, /* ###### */ |
|||
0xf0, 0x00, /* #### */ |
|||
0x08, 0x01, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x08, 0x01, /* # # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x04, 0x02, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x08, 0x01, /* # # */ |
|||
0xf0, 0x00, /* #### */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x24, 0x00, /* # # */ |
|||
0x24, 0x00, /* # # */ |
|||
0x24, 0x00, /* # # */ |
|||
0x04, 0x00, /* # */ |
|||
0xf0, 0x00, /* #### */ |
|||
0x08, 0x01, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x44, 0x02, /* # # # */ |
|||
0x48, 0x01, /* # # # */ |
|||
0xc0, 0x00, /* ## */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x20, 0x00, /* # */ |
|||
0x20, 0x00, /* # */ |
|||
0x20, 0x00, /* # */ |
|||
0x20, 0x00, /* # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x80, 0x01, /* ## */ |
|||
0x00, 0x02, /* # */ |
|||
0x00, 0x02, /* # */ |
|||
0xfc, 0x01, /* ####### */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x40, 0x00, /* # */ |
|||
0x20, 0x00, /* # */ |
|||
0x70, 0x00, /* ### */ |
|||
0x88, 0x01, /* ## # */ |
|||
0x04, 0x02, /* # # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x00, 0x02, /* # */ |
|||
0x00, 0x02, /* # */ |
|||
0x00, 0x02, /* # */ |
|||
0x00, 0x02, /* # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x18, 0x00, /* ## */ |
|||
0xe0, 0x00, /* ### */ |
|||
0x00, 0x03, /* ## */ |
|||
0xe0, 0x00, /* ### */ |
|||
0x18, 0x00, /* ## */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x08, 0x00, /* # */ |
|||
0x30, 0x00, /* ## */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x00, 0x01, /* # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0xf0, 0x00, /* #### */ |
|||
0x08, 0x01, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x08, 0x01, /* # # */ |
|||
0xf0, 0x00, /* #### */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x44, 0x00, /* # # */ |
|||
0x44, 0x00, /* # # */ |
|||
0x44, 0x00, /* # # */ |
|||
0x38, 0x00, /* ### */ |
|||
0xf0, 0x00, /* #### */ |
|||
0x08, 0x01, /* # # */ |
|||
0x04, 0x02, /* # # */ |
|||
0x84, 0x02, /* # # # */ |
|||
0x84, 0x02, /* # # # */ |
|||
0x08, 0x01, /* # # */ |
|||
0xf0, 0x02, /* # #### */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x24, 0x00, /* # # */ |
|||
0x24, 0x00, /* # # */ |
|||
0x64, 0x00, /* ## # */ |
|||
0xa4, 0x01, /* ## # # */ |
|||
0x18, 0x02, /* # ## */ |
|||
0x18, 0x01, /* # ## */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x24, 0x02, /* # # # */ |
|||
0x44, 0x02, /* # # # */ |
|||
0x44, 0x02, /* # # # */ |
|||
0x88, 0x01, /* ## # */ |
|||
0x04, 0x00, /* # */ |
|||
0x04, 0x00, /* # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x04, 0x00, /* # */ |
|||
0x04, 0x00, /* # */ |
|||
0xfc, 0x01, /* ####### */ |
|||
0x00, 0x02, /* # */ |
|||
0x00, 0x02, /* # */ |
|||
0x00, 0x02, /* # */ |
|||
0x00, 0x02, /* # */ |
|||
0xfc, 0x01, /* ####### */ |
|||
0x0c, 0x00, /* ## */ |
|||
0x30, 0x00, /* ## */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x00, 0x03, /* ## */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x30, 0x00, /* ## */ |
|||
0x0c, 0x00, /* ## */ |
|||
0xf0, 0x00, /* #### */ |
|||
0x00, 0x03, /* ## */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x38, 0x00, /* ### */ |
|||
0x04, 0x00, /* # */ |
|||
0x38, 0x00, /* ### */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x00, 0x03, /* ## */ |
|||
0xf0, 0x00, /* #### */ |
|||
0x0c, 0x00, /* ## */ |
|||
0x04, 0x02, /* # # */ |
|||
0x98, 0x01, /* ## ## */ |
|||
0x60, 0x00, /* ## */ |
|||
0x60, 0x00, /* ## */ |
|||
0x98, 0x01, /* ## ## */ |
|||
0x04, 0x02, /* # # */ |
|||
0x04, 0x00, /* # */ |
|||
0x18, 0x00, /* ## */ |
|||
0x20, 0x00, /* # */ |
|||
0xc0, 0x03, /* #### */ |
|||
0x20, 0x00, /* # */ |
|||
0x18, 0x00, /* ## */ |
|||
0x04, 0x00, /* # */ |
|||
0x00, 0x02, /* # */ |
|||
0x04, 0x03, /* ## # */ |
|||
0xc4, 0x02, /* # ## # */ |
|||
0x34, 0x02, /* # ## # */ |
|||
0x0c, 0x02, /* # ## */ |
|||
0x04, 0x02, /* # # */ |
|||
0xfc, 0x0f, /* ########## */ |
|||
0x04, 0x08, /* # # */ |
|||
0x0c, 0x00, /* ## */ |
|||
0xf0, 0x00, /* #### */ |
|||
0x00, 0x03, /* ## */ |
|||
0x04, 0x08, /* # # */ |
|||
0xfc, 0x0f, /* ########## */ |
|||
0x20, 0x00, /* # */ |
|||
0x18, 0x00, /* ## */ |
|||
0x04, 0x00, /* # */ |
|||
0x18, 0x00, /* ## */ |
|||
0x20, 0x00, /* # */ |
|||
0x00, 0x08, /* # */ |
|||
0x00, 0x08, /* # */ |
|||
0x00, 0x08, /* # */ |
|||
0x00, 0x08, /* # */ |
|||
0x00, 0x08, /* # */ |
|||
0x00, 0x08, /* # */ |
|||
0x04, 0x00, /* # */ |
|||
0x08, 0x00, /* # */ |
|||
0xa0, 0x01, /* ## # */ |
|||
0x50, 0x02, /* # # # */ |
|||
0x50, 0x02, /* # # # */ |
|||
0x50, 0x01, /* # # # */ |
|||
0xe0, 0x03, /* ##### */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x20, 0x01, /* # # */ |
|||
0x10, 0x02, /* # # */ |
|||
0x10, 0x02, /* # # */ |
|||
0xe0, 0x01, /* #### */ |
|||
0xe0, 0x01, /* #### */ |
|||
0x10, 0x02, /* # # */ |
|||
0x10, 0x02, /* # # */ |
|||
0x10, 0x02, /* # # */ |
|||
0x20, 0x01, /* # # */ |
|||
0xe0, 0x01, /* #### */ |
|||
0x10, 0x02, /* # # */ |
|||
0x10, 0x02, /* # # */ |
|||
0x20, 0x01, /* # # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0xe0, 0x01, /* #### */ |
|||
0x50, 0x02, /* # # # */ |
|||
0x50, 0x02, /* # # # */ |
|||
0x50, 0x02, /* # # # */ |
|||
0x60, 0x01, /* # ## */ |
|||
0x10, 0x00, /* # */ |
|||
0xf8, 0x03, /* ####### */ |
|||
0x14, 0x00, /* # # */ |
|||
0xe0, 0x09, /* # #### */ |
|||
0x10, 0x0a, /* # # # */ |
|||
0x10, 0x0a, /* # # # */ |
|||
0x20, 0x09, /* # # # */ |
|||
0xf0, 0x07, /* ####### */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x20, 0x00, /* # */ |
|||
0x10, 0x00, /* # */ |
|||
0x10, 0x00, /* # */ |
|||
0xe0, 0x03, /* ##### */ |
|||
0xf4, 0x03, /* ###### # */ |
|||
0xf4, 0x07, /* ####### # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x40, 0x00, /* # */ |
|||
0xa0, 0x01, /* ## # */ |
|||
0x10, 0x02, /* # # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0xf0, 0x03, /* ###### */ |
|||
0x20, 0x00, /* # */ |
|||
0x10, 0x00, /* # */ |
|||
0xf0, 0x03, /* ###### */ |
|||
0x20, 0x00, /* # */ |
|||
0x10, 0x00, /* # */ |
|||
0xe0, 0x03, /* ##### */ |
|||
0xf0, 0x03, /* ###### */ |
|||
0x10, 0x00, /* # */ |
|||
0x10, 0x00, /* # */ |
|||
0x10, 0x00, /* # */ |
|||
0xe0, 0x03, /* ##### */ |
|||
0xe0, 0x01, /* #### */ |
|||
0x10, 0x02, /* # # */ |
|||
0x10, 0x02, /* # # */ |
|||
0x10, 0x02, /* # # */ |
|||
0xe0, 0x01, /* #### */ |
|||
0xf0, 0x0f, /* ######## */ |
|||
0x20, 0x01, /* # # */ |
|||
0x10, 0x02, /* # # */ |
|||
0x10, 0x02, /* # # */ |
|||
0xe0, 0x01, /* #### */ |
|||
0xe0, 0x01, /* #### */ |
|||
0x10, 0x02, /* # # */ |
|||
0x10, 0x02, /* # # */ |
|||
0x20, 0x01, /* # # */ |
|||
0xf0, 0x0f, /* ######## */ |
|||
0xf0, 0x03, /* ###### */ |
|||
0x20, 0x00, /* # */ |
|||
0x10, 0x00, /* # */ |
|||
0x20, 0x01, /* # # */ |
|||
0x50, 0x02, /* # # # */ |
|||
0x50, 0x02, /* # # # */ |
|||
0x90, 0x02, /* # # # */ |
|||
0x20, 0x01, /* # # */ |
|||
0xfc, 0x03, /* ######## */ |
|||
0x10, 0x02, /* # # */ |
|||
0xf0, 0x01, /* ##### */ |
|||
0x00, 0x02, /* # */ |
|||
0x00, 0x02, /* # */ |
|||
0x00, 0x01, /* # */ |
|||
0xf0, 0x03, /* ###### */ |
|||
0x30, 0x00, /* ## */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x00, 0x03, /* ## */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x30, 0x00, /* ## */ |
|||
0x30, 0x00, /* ## */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x00, 0x03, /* ## */ |
|||
0xe0, 0x00, /* ### */ |
|||
0x10, 0x00, /* # */ |
|||
0xe0, 0x00, /* ### */ |
|||
0x00, 0x03, /* ## */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x30, 0x00, /* ## */ |
|||
0x10, 0x02, /* # # */ |
|||
0x20, 0x01, /* # # */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x20, 0x01, /* # # */ |
|||
0x10, 0x02, /* # # */ |
|||
0x10, 0x00, /* # */ |
|||
0xe0, 0x09, /* # #### */ |
|||
0x00, 0x07, /* ### */ |
|||
0xc0, 0x00, /* ## */ |
|||
0x30, 0x00, /* ## */ |
|||
0x10, 0x02, /* # # */ |
|||
0x10, 0x03, /* ## # */ |
|||
0x90, 0x02, /* # # # */ |
|||
0x70, 0x02, /* # ### */ |
|||
0x10, 0x02, /* # # */ |
|||
0x40, 0x00, /* # */ |
|||
0xb8, 0x07, /* #### ### */ |
|||
0x04, 0x08, /* # # */ |
|||
0xfc, 0x0f, /* ########## */ |
|||
0x00, 0x00, /* */ |
|||
0x04, 0x08, /* # # */ |
|||
0xb8, 0x07, /* #### ### */ |
|||
0x40, 0x00, /* # */ |
|||
0x60, 0x00, /* ## */ |
|||
0x20, 0x00, /* # */ |
|||
0x60, 0x00, /* ## */ |
|||
0x40, 0x00, /* # */ |
|||
0x20, 0x00, /* # */ |
|||
}; |
|||
|
|||
font font_arial8 = {13, fontIndex_arial8, fontData_arial8, ' ', '~', '.', 2}; |
@ -0,0 +1,8 @@ |
|||
#ifndef FONT_ARIAL8_H |
|||
#define FONT_ARIAL8_H |
|||
|
|||
#include "font.h" |
|||
extern font font_arial8; |
|||
|
|||
#endif /* FONT_ARIAL8_H */ |
|||
|
@ -0,0 +1,439 @@ |
|||
#include "font.h" |
|||
|
|||
unsigned int PROGMEM fontIndex_small6[] = { |
|||
0, /* */ |
|||
1, /* ! */ |
|||
2, /* " */ |
|||
5, /* # */ |
|||
10, /* $ */ |
|||
13, /* % */ |
|||
17, /* & */ |
|||
21, /* ' */ |
|||
22, /* ( */ |
|||
24, /* ) */ |
|||
26, /* * */ |
|||
28, /* + */ |
|||
31, /* , */ |
|||
32, /* - */ |
|||
34, /* . */ |
|||
35, /* / */ |
|||
37, /* 0 */ |
|||
41, /* 1 */ |
|||
43, /* 2 */ |
|||
47, /* 3 */ |
|||
51, /* 4 */ |
|||
55, /* 5 */ |
|||
58, /* 6 */ |
|||
62, /* 7 */ |
|||
65, /* 8 */ |
|||
69, /* 9 */ |
|||
73, /* : */ |
|||
74, /* ; */ |
|||
75, /* < */ |
|||
78, /* = */ |
|||
81, /* > */ |
|||
84, /* ? */ |
|||
88, /* @ */ |
|||
95, /* A */ |
|||
100, /* B */ |
|||
105, /* C */ |
|||
110, /* D */ |
|||
115, /* E */ |
|||
119, /* F */ |
|||
123, /* G */ |
|||
128, /* H */ |
|||
132, /* I */ |
|||
133, /* J */ |
|||
136, /* K */ |
|||
140, /* L */ |
|||
143, /* M */ |
|||
150, /* N */ |
|||
155, /* O */ |
|||
160, /* P */ |
|||
164, /* Q */ |
|||
169, /* R */ |
|||
174, /* S */ |
|||
178, /* T */ |
|||
182, /* U */ |
|||
187, /* V */ |
|||
192, /* W */ |
|||
199, /* X */ |
|||
204, /* Y */ |
|||
209, /* Z */ |
|||
213, /* [ */ |
|||
215, /* \ */ |
|||
217, /* ] */ |
|||
219, /* ^ */ |
|||
222, /* _ */ |
|||
226, /* ` */ |
|||
228, /* a */ |
|||
231, /* b */ |
|||
235, /* c */ |
|||
238, /* d */ |
|||
242, /* e */ |
|||
245, /* f */ |
|||
247, /* g */ |
|||
251, /* h */ |
|||
254, /* i */ |
|||
255, /* j */ |
|||
256, /* k */ |
|||
259, /* l */ |
|||
260, /* m */ |
|||
265, /* n */ |
|||
268, /* o */ |
|||
272, /* p */ |
|||
276, /* q */ |
|||
280, /* r */ |
|||
282, /* s */ |
|||
285, /* t */ |
|||
287, /* u */ |
|||
290, /* v */ |
|||
293, /* w */ |
|||
298, /* x */ |
|||
301, /* y */ |
|||
304, /* z */ |
|||
307, /* { */ |
|||
309, /* | */ |
|||
310, /* } */ |
|||
312, /* ~ */ |
|||
316, /* ß */ |
|||
321, /* ä */ |
|||
324, /* ö */ |
|||
328, /* ü */ |
|||
331 |
|||
}; |
|||
|
|||
unsigned char PROGMEM fontData_small6[] = { |
|||
0x00, /* */ |
|||
0x2f, /* # #### */ |
|||
0x03, /* ## */ |
|||
0x00, /* */ |
|||
0x03, /* ## */ |
|||
0x12, /* # # */ |
|||
0x3f, /* ###### */ |
|||
0x12, /* # # */ |
|||
0x3f, /* ###### */ |
|||
0x12, /* # # */ |
|||
0x26, /* # ## */ |
|||
0x7f, /* ####### */ |
|||
0x32, /* ## # */ |
|||
0x13, /* # ## */ |
|||
0x0b, /* # ## */ |
|||
0x34, /* ## # */ |
|||
0x32, /* ## # */ |
|||
0x1a, /* ## # */ |
|||
0x25, /* # # # */ |
|||
0x1a, /* ## # */ |
|||
0x28, /* # # */ |
|||
0x03, /* ## */ |
|||
0x7e, /* ###### */ |
|||
0x81, /* # # */ |
|||
0x81, /* # # */ |
|||
0x7e, /* ###### */ |
|||
0x03, /* ## */ |
|||
0x03, /* ## */ |
|||
0x08, /* # */ |
|||
0x1c, /* ### */ |
|||
0x08, /* # */ |
|||
0x60, /* ## */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x20, /* # */ |
|||
0x38, /* ### */ |
|||
0x07, /* ### */ |
|||
0x1e, /* #### */ |
|||
0x21, /* # # */ |
|||
0x21, /* # # */ |
|||
0x1e, /* #### */ |
|||
0x02, /* # */ |
|||
0x3f, /* ###### */ |
|||
0x32, /* ## # */ |
|||
0x29, /* # # # */ |
|||
0x29, /* # # # */ |
|||
0x26, /* # ## */ |
|||
0x12, /* # # */ |
|||
0x21, /* # # */ |
|||
0x25, /* # # # */ |
|||
0x1a, /* ## # */ |
|||
0x18, /* ## */ |
|||
0x16, /* # ## */ |
|||
0x3f, /* ###### */ |
|||
0x10, /* # */ |
|||
0x27, /* # ### */ |
|||
0x25, /* # # # */ |
|||
0x19, /* ## # */ |
|||
0x1e, /* #### */ |
|||
0x25, /* # # # */ |
|||
0x25, /* # # # */ |
|||
0x18, /* ## */ |
|||
0x01, /* # */ |
|||
0x3d, /* #### # */ |
|||
0x03, /* ## */ |
|||
0x1a, /* ## # */ |
|||
0x25, /* # # # */ |
|||
0x25, /* # # # */ |
|||
0x1a, /* ## # */ |
|||
0x12, /* # # */ |
|||
0x25, /* # # # */ |
|||
0x25, /* # # # */ |
|||
0x1e, /* #### */ |
|||
0x24, /* # # */ |
|||
0x64, /* ## # */ |
|||
0x08, /* # */ |
|||
0x14, /* # # */ |
|||
0x22, /* # # */ |
|||
0x14, /* # # */ |
|||
0x14, /* # # */ |
|||
0x14, /* # # */ |
|||
0x22, /* # # */ |
|||
0x14, /* # # */ |
|||
0x08, /* # */ |
|||
0x02, /* # */ |
|||
0x29, /* # # # */ |
|||
0x05, /* # # */ |
|||
0x02, /* # */ |
|||
0x1c, /* ### */ |
|||
0x22, /* # # */ |
|||
0x49, /* # # # */ |
|||
0x55, /* # # # # */ |
|||
0x59, /* # ## # */ |
|||
0x12, /* # # */ |
|||
0x0c, /* ## */ |
|||
0x30, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x0b, /* # ## */ |
|||
0x0c, /* ## */ |
|||
0x30, /* ## */ |
|||
0x3f, /* ###### */ |
|||
0x25, /* # # # */ |
|||
0x25, /* # # # */ |
|||
0x25, /* # # # */ |
|||
0x1a, /* ## # */ |
|||
0x1e, /* #### */ |
|||
0x21, /* # # */ |
|||
0x21, /* # # */ |
|||
0x21, /* # # */ |
|||
0x12, /* # # */ |
|||
0x3f, /* ###### */ |
|||
0x21, /* # # */ |
|||
0x21, /* # # */ |
|||
0x21, /* # # */ |
|||
0x1e, /* #### */ |
|||
0x3f, /* ###### */ |
|||
0x25, /* # # # */ |
|||
0x25, /* # # # */ |
|||
0x21, /* # # */ |
|||
0x3f, /* ###### */ |
|||
0x05, /* # # */ |
|||
0x05, /* # # */ |
|||
0x01, /* # */ |
|||
0x1e, /* #### */ |
|||
0x21, /* # # */ |
|||
0x21, /* # # */ |
|||
0x29, /* # # # */ |
|||
0x3a, /* ### # */ |
|||
0x3f, /* ###### */ |
|||
0x04, /* # */ |
|||
0x04, /* # */ |
|||
0x3f, /* ###### */ |
|||
0x3f, /* ###### */ |
|||
0x30, /* ## */ |
|||
0x20, /* # */ |
|||
0x1f, /* ##### */ |
|||
0x3f, /* ###### */ |
|||
0x0c, /* ## */ |
|||
0x12, /* # # */ |
|||
0x21, /* # # */ |
|||
0x3f, /* ###### */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x3f, /* ###### */ |
|||
0x03, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x30, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x03, /* ## */ |
|||
0x3f, /* ###### */ |
|||
0x3f, /* ###### */ |
|||
0x03, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x30, /* ## */ |
|||
0x3f, /* ###### */ |
|||
0x1e, /* #### */ |
|||
0x21, /* # # */ |
|||
0x21, /* # # */ |
|||
0x21, /* # # */ |
|||
0x1e, /* #### */ |
|||
0x3f, /* ###### */ |
|||
0x09, /* # # */ |
|||
0x09, /* # # */ |
|||
0x06, /* ## */ |
|||
0x1e, /* #### */ |
|||
0x21, /* # # */ |
|||
0x29, /* # # # */ |
|||
0x11, /* # # */ |
|||
0x2e, /* # ### */ |
|||
0x3f, /* ###### */ |
|||
0x09, /* # # */ |
|||
0x09, /* # # */ |
|||
0x09, /* # # */ |
|||
0x36, /* ## ## */ |
|||
0x12, /* # # */ |
|||
0x25, /* # # # */ |
|||
0x29, /* # # # */ |
|||
0x12, /* # # */ |
|||
0x01, /* # */ |
|||
0x3f, /* ###### */ |
|||
0x01, /* # */ |
|||
0x01, /* # */ |
|||
0x1f, /* ##### */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x1f, /* ##### */ |
|||
0x03, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x30, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x03, /* ## */ |
|||
0x03, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x30, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x30, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x03, /* ## */ |
|||
0x21, /* # # */ |
|||
0x12, /* # # */ |
|||
0x0c, /* ## */ |
|||
0x12, /* # # */ |
|||
0x21, /* # # */ |
|||
0x01, /* # */ |
|||
0x02, /* # */ |
|||
0x3c, /* #### */ |
|||
0x02, /* # */ |
|||
0x01, /* # */ |
|||
0x31, /* ## # */ |
|||
0x29, /* # # # */ |
|||
0x25, /* # # # */ |
|||
0x23, /* # ## */ |
|||
0x7f, /* ####### */ |
|||
0x41, /* # # */ |
|||
0x07, /* ### */ |
|||
0x38, /* ### */ |
|||
0x41, /* # # */ |
|||
0x7f, /* ####### */ |
|||
0x02, /* # */ |
|||
0x01, /* # */ |
|||
0x02, /* # */ |
|||
0x40, /* # */ |
|||
0x40, /* # */ |
|||
0x40, /* # */ |
|||
0x40, /* # */ |
|||
0x00, /* */ |
|||
0x01, /* # */ |
|||
0x14, /* # # */ |
|||
0x24, /* # # */ |
|||
0x38, /* ### */ |
|||
0x3f, /* ###### */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x18, /* ## */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x3f, /* ###### */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x28, /* # # */ |
|||
0x3e, /* ##### */ |
|||
0x05, /* # # */ |
|||
0x18, /* ## */ |
|||
0xa4, /* # # # */ |
|||
0xa4, /* # # # */ |
|||
0x7c, /* ##### */ |
|||
0x3f, /* ###### */ |
|||
0x04, /* # */ |
|||
0x38, /* ### */ |
|||
0x3d, /* #### # */ |
|||
0xfd, /* ###### # */ |
|||
0x3f, /* ###### */ |
|||
0x08, /* # */ |
|||
0x34, /* ## # */ |
|||
0x3f, /* ###### */ |
|||
0x3c, /* #### */ |
|||
0x04, /* # */ |
|||
0x3c, /* #### */ |
|||
0x04, /* # */ |
|||
0x38, /* ### */ |
|||
0x3c, /* #### */ |
|||
0x04, /* # */ |
|||
0x38, /* ### */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x18, /* ## */ |
|||
0xfc, /* ###### */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x18, /* ## */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0xfc, /* ###### */ |
|||
0x3c, /* #### */ |
|||
0x04, /* # */ |
|||
0x28, /* # # */ |
|||
0x24, /* # # */ |
|||
0x14, /* # # */ |
|||
0x1e, /* #### */ |
|||
0x24, /* # # */ |
|||
0x1c, /* ### */ |
|||
0x20, /* # */ |
|||
0x3c, /* #### */ |
|||
0x0c, /* ## */ |
|||
0x30, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x30, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x30, /* ## */ |
|||
0x0c, /* ## */ |
|||
0x24, /* # # */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x9c, /* # ### */ |
|||
0x60, /* ## */ |
|||
0x1c, /* ### */ |
|||
0x34, /* ## # */ |
|||
0x24, /* # # */ |
|||
0x2c, /* # ## */ |
|||
0x08, /* # */ |
|||
0x77, /* ### ### */ |
|||
0x7f, /* ####### */ |
|||
0x77, /* ### ### */ |
|||
0x08, /* # */ |
|||
0x01, /* # */ |
|||
0x02, /* # */ |
|||
0x01, /* # */ |
|||
0x02, /* # */ |
|||
0x3e, /* ##### */ |
|||
0x05, /* # # */ |
|||
0x26, /* # ## */ |
|||
0x18, /* ## */ |
|||
0x19, /* ## # */ |
|||
0x24, /* # # */ |
|||
0x29, /* # # # */ |
|||
0x19, /* ## # */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x19, /* ## # */ |
|||
0x1d, /* ### # */ |
|||
0x20, /* # */ |
|||
0x3d, /* #### # */ |
|||
}; |
|||
|
|||
font font_small6 = {8, fontIndex_small6, fontData_small6, ' ', '~', '.', 1}; |
@ -0,0 +1,7 @@ |
|||
#ifndef FONT_SMALL6_H |
|||
#define FONT_SMALL6_H |
|||
|
|||
#include "font.h" |
|||
extern font font_small6; |
|||
|
|||
#endif /* FONT_SMALL6_H_ */ |
@ -0,0 +1,503 @@ |
|||
#include "font.h" |
|||
|
|||
static unsigned int PROGMEM fontIndex_uni53[] = { 0, /* */ |
|||
1, /* ! */ |
|||
3, /* " */ |
|||
6, /* # */ |
|||
11, /* $ */ |
|||
16, /* % */ |
|||
21, /* & */ |
|||
27, /* ' */ |
|||
28, /* ( */ |
|||
30, /* ) */ |
|||
32, /* * */ |
|||
37, /* + */ |
|||
42, /* , */ |
|||
44, /* - */ |
|||
48, /* . */ |
|||
49, /* / */ |
|||
54, /* 0 */ |
|||
59, /* 1 */ |
|||
61, /* 2 */ |
|||
66, /* 3 */ |
|||
71, /* 4 */ |
|||
76, /* 5 */ |
|||
81, /* 6 */ |
|||
86, /* 7 */ |
|||
90, /* 8 */ |
|||
95, /* 9 */ |
|||
100, /* : */ |
|||
102, /* ; */ |
|||
104, /* < */ |
|||
107, /* = */ |
|||
112, /* > */ |
|||
115, /* ? */ |
|||
119, /* @ */ |
|||
124, /* A */ |
|||
129, /* B */ |
|||
134, /* C */ |
|||
139, /* D */ |
|||
144, /* E */ |
|||
149, /* F */ |
|||
154, /* G */ |
|||
159, /* H */ |
|||
164, /* I */ |
|||
165, /* J */ |
|||
169, /* K */ |
|||
174, /* L */ |
|||
178, /* M */ |
|||
183, /* N */ |
|||
188, /* O */ |
|||
193, /* P */ |
|||
198, /* Q */ |
|||
203, /* R */ |
|||
208, /* S */ |
|||
213, /* T */ |
|||
218, /* U */ |
|||
223, /* V */ |
|||
228, /* W */ |
|||
235, /* X */ |
|||
240, /* Y */ |
|||
245, /* Z */ |
|||
250, /* [ */ |
|||
252, /* \ */ |
|||
257, /* ] */ |
|||
259, /* ^ */ |
|||
262, /* _ */ |
|||
267, /* ` */ |
|||
269, /* a */ |
|||
273, /* b */ |
|||
277, /* c */ |
|||
281, /* d */ |
|||
285, /* e */ |
|||
289, /* f */ |
|||
291, /* g */ |
|||
295, /* h */ |
|||
299, /* i */ |
|||
300, /* j */ |
|||
302, /* k */ |
|||
306, /* l */ |
|||
307, /* m */ |
|||
314, /* n */ |
|||
318, /* o */ |
|||
322, /* p */ |
|||
326, /* q */ |
|||
330, /* r */ |
|||
333, /* s */ |
|||
337, /* t */ |
|||
340, /* u */ |
|||
344, /* v */ |
|||
348, /* w */ |
|||
355, /* x */ |
|||
359, /* y */ |
|||
363, /* z */ |
|||
367, /* { */ |
|||
370, /* | */ |
|||
372, /* } */ |
|||
375, /* ~ */ |
|||
379, /* ß */ |
|||
383, /* ä */ |
|||
387, /* ö */ |
|||
391, /* ü */ |
|||
395 |
|||
}; |
|||
|
|||
static unsigned char PROGMEM fontData_uni53[] = { |
|||
0x00, /* */ |
|||
0x00, /* */ |
|||
0x2e, /* # ### */ |
|||
0x06, /* ## */ |
|||
0x00, /* */ |
|||
0x06, /* ## */ |
|||
0x14, /* # # */ |
|||
0x3e, /* ##### */ |
|||
0x14, /* # # */ |
|||
0x3e, /* ##### */ |
|||
0x14, /* # # */ |
|||
0x24, /* # # */ |
|||
0x2a, /* # # # */ |
|||
0x6b, /* ## # ## */ |
|||
0x2a, /* # # # */ |
|||
0x12, /* # # */ |
|||
0x22, /* # # */ |
|||
0x10, /* # */ |
|||
0x08, /* # */ |
|||
0x04, /* # */ |
|||
0x22, /* # # */ |
|||
0x14, /* # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x24, /* # # */ |
|||
0x10, /* # */ |
|||
0x06, /* ## */ |
|||
0x3e, /* ##### */ |
|||
0x41, /* # # */ |
|||
0x41, /* # # */ |
|||
0x3e, /* ##### */ |
|||
0x08, /* # */ |
|||
0x2a, /* # # # */ |
|||
0x1c, /* ### */ |
|||
0x2a, /* # # # */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x3e, /* ##### */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x80, /* # */ |
|||
0x60, /* ## */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x10, /* # */ |
|||
0x08, /* # */ |
|||
0x04, /* # */ |
|||
0x02, /* # */ |
|||
0x1c, /* ### */ |
|||
0x22, /* # # */ |
|||
0x22, /* # # */ |
|||
0x22, /* # # */ |
|||
0x1c, /* ### */ |
|||
0x02, /* # */ |
|||
0x3e, /* ##### */ |
|||
0x32, /* ## # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x2c, /* # ## */ |
|||
0x22, /* # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x14, /* # # */ |
|||
0x0e, /* ### */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x3e, /* ##### */ |
|||
0x2e, /* # ### */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x12, /* # # */ |
|||
0x1c, /* ### */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x10, /* # */ |
|||
0x02, /* # */ |
|||
0x02, /* # */ |
|||
0x32, /* ## # */ |
|||
0x0e, /* ### */ |
|||
0x14, /* # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x14, /* # # */ |
|||
0x04, /* # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x1c, /* ### */ |
|||
0x00, /* */ |
|||
0x14, /* # # */ |
|||
0x80, /* # */ |
|||
0x64, /* ## # */ |
|||
0x08, /* # */ |
|||
0x14, /* # # */ |
|||
0x22, /* # # */ |
|||
0x14, /* # # */ |
|||
0x14, /* # # */ |
|||
0x14, /* # # */ |
|||
0x14, /* # # */ |
|||
0x14, /* # # */ |
|||
0x22, /* # # */ |
|||
0x14, /* # # */ |
|||
0x08, /* # */ |
|||
0x02, /* # */ |
|||
0x2a, /* # # # */ |
|||
0x0a, /* # # */ |
|||
0x04, /* # */ |
|||
0x1c, /* ### */ |
|||
0x22, /* # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x0c, /* ## */ |
|||
0x3c, /* #### */ |
|||
0x0a, /* # # */ |
|||
0x0a, /* # # */ |
|||
0x0a, /* # # */ |
|||
0x3c, /* #### */ |
|||
0x3e, /* ##### */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x14, /* # # */ |
|||
0x1c, /* ### */ |
|||
0x22, /* # # */ |
|||
0x22, /* # # */ |
|||
0x22, /* # # */ |
|||
0x14, /* # # */ |
|||
0x3e, /* ##### */ |
|||
0x22, /* # # */ |
|||
0x22, /* # # */ |
|||
0x22, /* # # */ |
|||
0x1c, /* ### */ |
|||
0x3e, /* ##### */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x22, /* # # */ |
|||
0x3e, /* ##### */ |
|||
0x0a, /* # # */ |
|||
0x0a, /* # # */ |
|||
0x0a, /* # # */ |
|||
0x02, /* # */ |
|||
0x1c, /* ### */ |
|||
0x22, /* # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x3a, /* ### # */ |
|||
0x3e, /* ##### */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x3e, /* ##### */ |
|||
0x3e, /* ##### */ |
|||
0x10, /* # */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x1e, /* #### */ |
|||
0x3e, /* ##### */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x14, /* # # */ |
|||
0x22, /* # # */ |
|||
0x3e, /* ##### */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x3e, /* ##### */ |
|||
0x04, /* # */ |
|||
0x08, /* # */ |
|||
0x04, /* # */ |
|||
0x3e, /* ##### */ |
|||
0x3e, /* ##### */ |
|||
0x04, /* # */ |
|||
0x08, /* # */ |
|||
0x10, /* # */ |
|||
0x3e, /* ##### */ |
|||
0x1c, /* ### */ |
|||
0x22, /* # # */ |
|||
0x22, /* # # */ |
|||
0x22, /* # # */ |
|||
0x1c, /* ### */ |
|||
0x3e, /* ##### */ |
|||
0x0a, /* # # */ |
|||
0x0a, /* # # */ |
|||
0x0a, /* # # */ |
|||
0x04, /* # */ |
|||
0x1c, /* ### */ |
|||
0x22, /* # # */ |
|||
0x22, /* # # */ |
|||
0x22, /* # # */ |
|||
0x5c, /* # ### */ |
|||
0x3e, /* ##### */ |
|||
0x0a, /* # # */ |
|||
0x0a, /* # # */ |
|||
0x1a, /* ## # */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x2a, /* # # # */ |
|||
0x12, /* # # */ |
|||
0x02, /* # */ |
|||
0x02, /* # */ |
|||
0x3e, /* ##### */ |
|||
0x02, /* # */ |
|||
0x02, /* # */ |
|||
0x1e, /* #### */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x1e, /* #### */ |
|||
0x0e, /* ### */ |
|||
0x10, /* # */ |
|||
0x20, /* # */ |
|||
0x10, /* # */ |
|||
0x0e, /* ### */ |
|||
0x1e, /* #### */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x1e, /* #### */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x1e, /* #### */ |
|||
0x22, /* # # */ |
|||
0x14, /* # # */ |
|||
0x08, /* # */ |
|||
0x14, /* # # */ |
|||
0x22, /* # # */ |
|||
0x02, /* # */ |
|||
0x04, /* # */ |
|||
0x38, /* ### */ |
|||
0x04, /* # */ |
|||
0x02, /* # */ |
|||
0x22, /* # # */ |
|||
0x32, /* ## # */ |
|||
0x2a, /* # # # */ |
|||
0x26, /* # ## */ |
|||
0x22, /* # # */ |
|||
0x7f, /* ####### */ |
|||
0x41, /* # # */ |
|||
0x02, /* # */ |
|||
0x04, /* # */ |
|||
0x08, /* # */ |
|||
0x10, /* # */ |
|||
0x20, /* # */ |
|||
0x41, /* # # */ |
|||
0x7f, /* ####### */ |
|||
0x04, /* # */ |
|||
0x02, /* # */ |
|||
0x04, /* # */ |
|||
0x40, /* # */ |
|||
0x40, /* # */ |
|||
0x40, /* # */ |
|||
0x40, /* # */ |
|||
0x40, /* # */ |
|||
0x02, /* # */ |
|||
0x04, /* # */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x38, /* ### */ |
|||
0x3e, /* ##### */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x18, /* ## */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x3e, /* ##### */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x34, /* ## # */ |
|||
0x2c, /* # ## */ |
|||
0x3c, /* #### */ |
|||
0x0a, /* # # */ |
|||
0x18, /* ## */ |
|||
0xa4, /* # # # */ |
|||
0xa4, /* # # # */ |
|||
0x78, /* #### */ |
|||
0x3e, /* ##### */ |
|||
0x04, /* # */ |
|||
0x04, /* # */ |
|||
0x38, /* ### */ |
|||
0x3a, /* ### # */ |
|||
0x80, /* # */ |
|||
0x7a, /* #### # */ |
|||
0x3e, /* ##### */ |
|||
0x10, /* # */ |
|||
0x08, /* # */ |
|||
0x34, /* ## # */ |
|||
0x3e, /* ##### */ |
|||
0x3c, /* #### */ |
|||
0x04, /* # */ |
|||
0x04, /* # */ |
|||
0x38, /* ### */ |
|||
0x04, /* # */ |
|||
0x04, /* # */ |
|||
0x38, /* ### */ |
|||
0x3c, /* #### */ |
|||
0x04, /* # */ |
|||
0x04, /* # */ |
|||
0x38, /* ### */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x18, /* ## */ |
|||
0xfc, /* ###### */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x18, /* ## */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0xfc, /* ###### */ |
|||
0x3c, /* #### */ |
|||
0x08, /* # */ |
|||
0x04, /* # */ |
|||
0x28, /* # # */ |
|||
0x2c, /* # ## */ |
|||
0x34, /* ## # */ |
|||
0x14, /* # # */ |
|||
0x04, /* # */ |
|||
0x3e, /* ##### */ |
|||
0x04, /* # */ |
|||
0x1c, /* ### */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x3c, /* #### */ |
|||
0x1c, /* ### */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x1c, /* ### */ |
|||
0x1c, /* ### */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x1c, /* ### */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x1c, /* ### */ |
|||
0x24, /* # # */ |
|||
0x18, /* ## */ |
|||
0x18, /* ## */ |
|||
0x24, /* # # */ |
|||
0x1c, /* ### */ |
|||
0xa0, /* # # */ |
|||
0xa0, /* # # */ |
|||
0x7c, /* ##### */ |
|||
0x24, /* # # */ |
|||
0x34, /* ## # */ |
|||
0x2c, /* # ## */ |
|||
0x24, /* # # */ |
|||
0x08, /* # */ |
|||
0x36, /* ## ## */ |
|||
0x41, /* # # */ |
|||
0x00, /* */ |
|||
0x7f, /* ####### */ |
|||
0x41, /* # # */ |
|||
0x36, /* ## ## */ |
|||
0x08, /* # */ |
|||
0x08, /* # */ |
|||
0x04, /* # */ |
|||
0x08, /* # */ |
|||
0x04, /* # */ |
|||
0x3c, /* #### */ |
|||
0x02, /* # */ |
|||
0x2a, /* # # # */ |
|||
0x14, /* # # */ |
|||
0x19, /* ## # */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x39, /* ### # */ |
|||
0x19, /* ## # */ |
|||
0x24, /* # # */ |
|||
0x24, /* # # */ |
|||
0x19, /* ## # */ |
|||
0x1d, /* ### # */ |
|||
0x20, /* # */ |
|||
0x20, /* # */ |
|||
0x3d, /* #### # */ |
|||
}; |
|||
|
|||
font font_uni53 = {8, fontIndex_uni53, fontData_uni53, ' ', '~', '.', 1}; |
@ -0,0 +1,8 @@ |
|||
#ifndef FONT_UNI53_H_ |
|||
#define FONT_UNI53_H_ |
|||
|
|||
#include "font.h" |
|||
extern font font_uni53; |
|||
|
|||
#endif /* FONT_UNI53_H_ */ |
|||
|
@ -0,0 +1,6 @@ |
|||
#ifndef SCROLLTEXT_H_ |
|||
#define SCROLLTEXT_H_ |
|||
|
|||
void scrolltext(char *str); |
|||
|
|||
#endif /* SCROLLTEXT_H_ */ |
@ -0,0 +1,578 @@ |
|||
#define SCROLLTEXT_C |
|||
|
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <setjmp.h> |
|||
|
|||
#include "../config.h" |
|||
#include "scrolltext.h" |
|||
#ifdef AVR |
|||
# include "../borg_hw/borg_hw.h" |
|||
#endif |
|||
|
|||
#include "../pixel.h" |
|||
#include "../util.h" |
|||
#include "font_arial8.h" |
|||
#include "font_small6.h" |
|||
#include "font_uni53.h" |
|||
|
|||
#define MAX_FONTS 1 |
|||
font fonts[MAX_FONTS]; |
|||
#define MAX_SPECIALCOLORS 3 |
|||
unsigned char PROGMEM colorTable[MAX_SPECIALCOLORS*NUM_ROWS] = {1, 1, 2, 3, 3, 2, 1, 1, |
|||
3, 3, 2, 1, 1, 2, 3, 3, |
|||
3, 3, 2, 2, 3, 3, 2, 2 |
|||
}; |
|||
|
|||
char default_text[] PROGMEM = SCROLLTEXT_TEXT; |
|||
char scrolltext_text[SCROLLTEXT_BUFFER_SIZE]; |
|||
|
|||
/* Konzept
|
|||
======= |
|||
Text wird in Token unterteilt, jeder Token bekommt einen Command-String. |
|||
z.B. |
|||
|
|||
#b</#LABOR |
|||
|
|||
Es werden die Zeiger aus dem Eingabestring direkt übernommen, mit Stringlen. |
|||
Wenn der Command abgearbeitet ist wird automatisch das nächste Token eingelesen. |
|||
|
|||
*/ |
|||
|
|||
|
|||
unsigned char (*text_pixmap)[NUM_ROWS][LINEBYTES]; |
|||
|
|||
void text_setpixel(pixel p, unsigned char value ){ |
|||
if(value){ |
|||
(*text_pixmap)[p.y%NUM_ROWS][p.x/8] |= shl_table[p.x%8]; |
|||
} |
|||
} |
|||
|
|||
void clear_text_pixmap(unsigned char value){ |
|||
unsigned char y, z; |
|||
for(y=0;y<NUM_ROWS;y++){ |
|||
for(z=0;z<LINEBYTES;z++){ |
|||
(*text_pixmap)[y][z] = 0; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
void update_pixmap(){ |
|||
unsigned char x, y, z; |
|||
for(x=0;x<NUMPLANE;x++){ |
|||
for(y=0;y<NUM_ROWS;y++){ |
|||
for(z=0;z<LINEBYTES;z++){ |
|||
pixmap[x][y][z] = (*text_pixmap)[y][z]; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
enum waitfor_e{ |
|||
wait_new, |
|||
wait_posy, |
|||
wait_posx, |
|||
wait_out, |
|||
wait_timer, |
|||
wait_col_l, |
|||
wait_col_r |
|||
}; |
|||
#define DIRECTION_RIGHT 0x01 |
|||
#define DIRECTION_DOWN 0x02 |
|||
|
|||
struct blob_t_struct; |
|||
typedef struct blob_t_struct{ |
|||
struct blob_t_struct * next, * last; |
|||
char *str; |
|||
char *commands; |
|||
enum waitfor_e waitfor; |
|||
int sizex; |
|||
char sizey; |
|||
int posx; |
|||
char posy; |
|||
int tox; |
|||
char toy; |
|||
unsigned char delayx, delayx_rld; |
|||
unsigned char delayy, delayy_rld; |
|||
unsigned char delayb, delayb_rld; |
|||
unsigned char visible; |
|||
unsigned char direction; |
|||
unsigned int timer; |
|||
|
|||
const unsigned int* fontIndex; |
|||
const unsigned char* fontData; |
|||
unsigned char font_storebytes;/*bytes per char*/ |
|||
unsigned char space; |
|||
}blob_t; |
|||
|
|||
|
|||
/*
|
|||
void showBlob(blob_t * blob){ |
|||
unsigned char * str = blob->str; |
|||
unsigned char tmp[200], x=0; |
|||
while(*str){ |
|||
tmp[x++] = (*str++) + ' ' -1; |
|||
} |
|||
tmp[x] = 0; |
|||
printf("this:\t%x\n",blob); |
|||
printf("last:\t%x\n",blob->last); |
|||
printf("next:\t%x\n",blob->next); |
|||
printf("str:\t%s\n",tmp); |
|||
printf("cmd:\t%s\n",blob->commands); |
|||
printf("sizex\t%d\n",blob->sizex); |
|||
printf("posx\t%d\n",blob->posx); |
|||
printf("posy\t%d\n",blob->posy); |
|||
printf("tox\t%d\n",blob->tox); |
|||
printf("toy\t%d\n",blob->toy); |
|||
printf("delayy_rld\t%d\n",blob->delayx_rld); |
|||
printf("delayx_rld\t%d\n",blob->delayy_rld); |
|||
printf("timer\t%d\n",blob->timer); |
|||
printf("\n"); |
|||
} |
|||
*/ |
|||
|
|||
|
|||
#define PW(a) pgm_read_word(&(a)) |
|||
#define PB(a) pgm_read_byte(&(a)) |
|||
|
|||
unsigned int getLen(blob_t *blob) { |
|||
unsigned char glyph; |
|||
unsigned int strLen = 0; |
|||
unsigned char * str = (unsigned char*)blob->str; |
|||
uint8_t space = blob->space * blob->font_storebytes; |
|||
|
|||
while ((glyph = *str++)) { |
|||
glyph -= 1; |
|||
strLen += PW(blob->fontIndex[glyph+1]) - PW(blob->fontIndex[glyph]); |
|||
strLen += space; |
|||
} |
|||
return strLen/blob->font_storebytes; |
|||
} |
|||
|
|||
|
|||
unsigned int getnum(blob_t * blob){ |
|||
unsigned int num=0; |
|||
unsigned char gotnum = 0; |
|||
|
|||
while( (*blob->commands >= '0') && (*blob->commands <='9') ){ |
|||
gotnum = 1; |
|||
num *= 10; |
|||
num += *blob->commands - '0'; |
|||
blob->commands++; |
|||
} |
|||
|
|||
if(gotnum){ |
|||
return num; |
|||
}else{ |
|||
return 0xffff; |
|||
} |
|||
} |
|||
|
|||
unsigned char blobNextCommand(blob_t * blob){ |
|||
unsigned int tmp; |
|||
unsigned char retval = 0; |
|||
while(*blob->commands != 0){ |
|||
switch (*blob->commands++){ |
|||
case '<': |
|||
blob->direction &= ~DIRECTION_RIGHT; |
|||
if((tmp = getnum(blob)) != 0xFFFF){ |
|||
blob->delayx_rld = tmp; |
|||
}else{ |
|||
blob->delayx_rld = SCROLL_X_SPEED; |
|||
} |
|||
blob->delayx = blob->delayx_rld; |
|||
break; |
|||
case '>': |
|||
blob->direction |= DIRECTION_RIGHT; |
|||
if((tmp = getnum(blob)) != 0xFFFF){ |
|||
blob->delayx_rld = tmp; |
|||
}else{ |
|||
blob->delayx_rld = SCROLL_X_SPEED; |
|||
} |
|||
blob->delayx = blob->delayx_rld; |
|||
break; |
|||
case 'd': |
|||
blob->direction |= DIRECTION_DOWN; |
|||
if((tmp = getnum(blob)) != 0xFFFF){ |
|||
blob->delayy_rld = tmp; |
|||
}else{ |
|||
blob->delayy_rld = SCROLL_Y_SPEED; |
|||
} |
|||
blob->delayy = blob->delayy_rld; |
|||
break; |
|||
case 'u': |
|||
blob->direction &= ~DIRECTION_DOWN; |
|||
if((tmp = getnum(blob)) != 0xFFFF){ |
|||
blob->delayy_rld = tmp; |
|||
}else{ |
|||
blob->delayy_rld = SCROLL_Y_SPEED; |
|||
} |
|||
blob->delayy = blob->delayy_rld; |
|||
break; |
|||
case 'x'://Place string at this x Position
|
|||
if((tmp = getnum(blob)) != 0xFFFF){ |
|||
blob->posx = tmp; |
|||
}else{ |
|||
blob->posx = NUM_COLS/2 + blob->sizex/2; |
|||
} |
|||
break; |
|||
case 'y'://Place string at this y Position
|
|||
if((tmp = getnum(blob)) != 0xFFFF){ |
|||
blob->posy = tmp - blob->sizey; |
|||
} |
|||
break; |
|||
case 'b'://blink blob
|
|||
if((tmp = getnum(blob)) != 0xFFFF){ |
|||
blob->delayb_rld = tmp; |
|||
}else{ |
|||
blob->delayb_rld = 50; |
|||
} |
|||
blob->delayb = blob->delayb_rld; |
|||
break; |
|||
case '|': |
|||
if((tmp = getnum(blob)) != 0xFFFF){ |
|||
blob->tox = tmp; |
|||
}else{ |
|||
blob->tox = (NUM_COLS - 2 + blob->sizex)/2; |
|||
} |
|||
blob->waitfor = wait_posx; |
|||
return retval; |
|||
break; |
|||
case '-': |
|||
if((tmp = getnum(blob)) != 0xFFFF){ |
|||
blob->toy = tmp; |
|||
}else{ |
|||
blob->toy = (NUM_ROWS-blob->sizey) / 2; |
|||
} |
|||
blob->waitfor = wait_posy; |
|||
return retval; |
|||
break; |
|||
case 'p': |
|||
blob->delayx_rld = 0; |
|||
blob->delayy_rld = 0; |
|||
if((tmp = getnum(blob)) != 0xFFFF){ |
|||
blob->timer = tmp*64; |
|||
}else{ |
|||
blob->timer = 30*64; |
|||
} |
|||
blob->waitfor = wait_timer; |
|||
return retval; |
|||
break; |
|||
case '/': |
|||
blob->waitfor = wait_out; |
|||
return retval; |
|||
break; |
|||
case ';': |
|||
blob->waitfor = wait_col_l; |
|||
return (retval); |
|||
break; |
|||
case ':': |
|||
blob->waitfor = wait_col_r; |
|||
return (retval); |
|||
break; |
|||
case '+': |
|||
retval = 2; |
|||
break; |
|||
} |
|||
} |
|||
return 1;//this blob is finished, and can be deleted.
|
|||
} |
|||
|
|||
|
|||
blob_t * setupBlob(char * str){ |
|||
/*char * strtok_r ( char * string, const char * delim, char ** last)*/ |
|||
static unsigned char chop_cnt; |
|||
static char *last; static char delim[] = "#"; |
|||
static char *lastcommands; |
|||
unsigned int tmp; |
|||
|
|||
if(str){ |
|||
chop_cnt = 0; |
|||
} |
|||
|
|||
blob_t *blob = malloc(sizeof (blob_t)); |
|||
|
|||
if(!chop_cnt){ |
|||
blob->commands = strtok_r (str, delim, &last); |
|||
if( blob->commands == 0) goto fail; |
|||
|
|||
if((tmp = getnum(blob)) != 0xFFFF){ |
|||
chop_cnt = tmp; |
|||
lastcommands = blob->commands; |
|||
} |
|||
} |
|||
|
|||
if(chop_cnt){ |
|||
chop_cnt--; |
|||
blob->commands = lastcommands; |
|||
} |
|||
|
|||
blob->str = strtok_r (0, delim, &last); |
|||
|
|||
if ( blob->str == 0) goto fail; |
|||
|
|||
blob->fontIndex = fonts[0].fontIndex; |
|||
blob->fontData = fonts[0].fontData; |
|||
blob->font_storebytes = fonts[0].storebytes; |
|||
|
|||
unsigned char tmp1, *strg = (unsigned char*)blob->str; |
|||
unsigned char glyph_beg = fonts[0].glyph_beg; |
|||
unsigned char glyph_end = fonts[0].glyph_end; |
|||
|
|||
//translate the string: subtract 1 to get offset in Table
|
|||
while((tmp1 = *strg)){ |
|||
if((tmp1>=glyph_beg) && (tmp1<glyph_end)){ |
|||
*strg = 1 + tmp1 - glyph_beg; |
|||
}else{ |
|||
*strg = 1; |
|||
} |
|||
strg++; |
|||
} |
|||
|
|||
blob->space = 1; |
|||
|
|||
blob->sizey = fonts[0].fontHeight; |
|||
blob->sizex = getLen(blob); |
|||
if(*blob->commands == '<'){ |
|||
blob->posx = 0; |
|||
blob->posy = (NUM_ROWS-blob->sizey)/2; |
|||
}else if(*blob->commands == '>'){ |
|||
blob->posx = NUM_COLS+blob->sizex; |
|||
blob->posy = (NUM_ROWS-blob->sizey)/2; |
|||
}else if(*blob->commands == 'd'){ |
|||
blob->posy = -blob->sizey; |
|||
blob->posx = (NUM_COLS - 2 + blob->sizex)/2; |
|||
}else if(*blob->commands == 'u'){ |
|||
blob->posy = blob->sizey; |
|||
blob->posx = (NUM_COLS - 2 + blob->sizex)/2; |
|||
} |
|||
|
|||
blob->delayx_rld = 0; |
|||
blob->delayy_rld = 0; |
|||
blob->delayb_rld = 0; |
|||
|
|||
blob->waitfor = wait_new; |
|||
|
|||
return blob; |
|||
|
|||
fail: |
|||
free(blob); |
|||
return 0;//no more blobs to parse
|
|||
} |
|||
|
|||
|
|||
unsigned char updateBlob(blob_t * blob){ |
|||
|
|||
if(blob->delayx_rld && (!(blob->delayx--))){ |
|||
blob->delayx = blob->delayx_rld; |
|||
(blob->direction & DIRECTION_RIGHT)?blob->posx--:blob->posx++; |
|||
} |
|||
|
|||
if(blob->delayy_rld && (!(blob->delayy--))){ |
|||
blob->delayy = blob->delayy_rld; |
|||
(blob->direction & DIRECTION_DOWN)?blob->posy++:blob->posy--; |
|||
} |
|||
|
|||
if(blob->delayb_rld){ |
|||
if(!(blob->delayb--)){ |
|||
blob->delayb = blob->delayb_rld; |
|||
blob->visible ^= 1; |
|||
} |
|||
}else{ |
|||
blob->visible = 1; |
|||
} |
|||
|
|||
unsigned char done=0; |
|||
switch (blob->waitfor){ |
|||
case wait_posy: |
|||
if (blob->posy == blob->toy)done = 1; |
|||
break; |
|||
case wait_posx: |
|||
if (blob->posx == blob->tox)done = 1; |
|||
break; |
|||
case wait_out: |
|||
if((blob->posx - blob->sizex) > NUM_COLS || blob->posx < 0) done = 1; |
|||
if((blob->posy) > NUM_ROWS || (blob->posy + blob->sizey) <0 ) done = 1; |
|||
break; |
|||
case wait_timer: |
|||
if(0 == blob->timer--){ |
|||
done = 1; |
|||
} |
|||
break; |
|||
case wait_col_l: |
|||
if(blob->last){ |
|||
if((blob->last->posx - blob->last->sizex) == blob->posx){ |
|||
done=1; |
|||
} |
|||
}else{ |
|||
done = 1; |
|||
} |
|||
break; |
|||
case wait_col_r: |
|||
if(blob->next){ |
|||
if(blob->next->posx == (blob->posx - blob->sizex)){ |
|||
done=1; |
|||
} |
|||
}else{ |
|||
done = 1; |
|||
} |
|||
break; |
|||
default: |
|||
done = 1; |
|||
break; |
|||
} |
|||
if(done){ |
|||
return (blobNextCommand(blob)); |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
void drawBlob(blob_t *blob) { |
|||
char x, y; |
|||
unsigned char byte=0, glyph, storebytes; |
|||
unsigned int charPos, charEnd; |
|||
|
|||
unsigned int posx; unsigned char posy, toy; |
|||
|
|||
if(!blob->visible) return; |
|||
|
|||
unsigned char * str = (unsigned char*)blob->str; |
|||
posx = blob->posx; |
|||
posy = blob->posy; |
|||
toy = posy + blob->sizey; |
|||
storebytes = blob->font_storebytes; |
|||
|
|||
glyph = (*blob->str)-1; |
|||
charPos = PW(blob->fontIndex[glyph]); |
|||
charEnd = PW(blob->fontIndex[glyph+1]); |
|||
|
|||
while (posx >= NUM_COLS) { |
|||
charPos += storebytes; |
|||
if (charPos < charEnd) { |
|||
posx--; |
|||
}else{ |
|||
posx -= blob->space + 1; |
|||
if (!(glyph = *++str)) return; |
|||
glyph -= 1; |
|||
charPos = PW(blob->fontIndex[glyph]); |
|||
charEnd = PW(blob->fontIndex[glyph+1]); |
|||
} |
|||
} |
|||
for (x = posx; x >= 0; x-- ) { |
|||
unsigned char mask = 0; |
|||
unsigned int datpos; |
|||
datpos = charPos; |
|||
|
|||
for (y = posy; (y < NUM_ROWS) && (y < toy); y++) { |
|||
|
|||
if((mask<<=1) == 0){ |
|||
mask = 0x01; |
|||
byte = PB(blob->fontData[datpos++]); |
|||
} |
|||
|
|||
if ((byte & mask) && y >= 0 ) { |
|||
text_setpixel((pixel){x, y},1); |
|||
} |
|||
} |
|||
charPos += storebytes; |
|||
if (charPos < charEnd) { |
|||
}else{ |
|||
x -= blob->space; |
|||
if (!(glyph = *++str)) return; |
|||
glyph -= 1; |
|||
charPos = PW(blob->fontIndex[glyph]); |
|||
charEnd = PW(blob->fontIndex[glyph+1]); |
|||
} |
|||
} |
|||
} |
|||
|
|||
extern jmp_buf newmode_jmpbuf; |
|||
|
|||
void scrolltext(char *str) { |
|||
jmp_buf tmp_jmpbuf; |
|||
char tmp_str[SCROLLTEXT_BUFFER_SIZE]; |
|||
int ljmp_retval; |
|||
|
|||
fonts[0] = SCROLLTEXT_FONT; |
|||
|
|||
text_pixmap = malloc(NUM_ROWS * LINEBYTES); |
|||
|
|||
if(scrolltext_text[0] == 0){ |
|||
strcpy_P(scrolltext_text, default_text); |
|||
} |
|||
memcpy(tmp_str, str, SCROLLTEXT_BUFFER_SIZE); |
|||
|
|||
blob_t *startblob=0, *aktblob, *nextblob=0; |
|||
|
|||
memcpy (tmp_jmpbuf, newmode_jmpbuf, sizeof(jmp_buf)); |
|||
|
|||
|
|||
if((ljmp_retval = setjmp(newmode_jmpbuf))){ |
|||
while(startblob){ |
|||
aktblob = startblob; |
|||
startblob = aktblob->next; |
|||
free(aktblob); |
|||
} |
|||
free(text_pixmap); |
|||
memcpy (newmode_jmpbuf, tmp_jmpbuf, sizeof(jmp_buf)); |
|||
longjmp(newmode_jmpbuf, ljmp_retval); |
|||
} |
|||
|
|||
if (!(startblob = setupBlob(tmp_str))){ |
|||
goto exit; |
|||
} |
|||
|
|||
unsigned char retval; |
|||
do{ |
|||
startblob->next = 0; |
|||
startblob->last = 0; |
|||
while(startblob){ |
|||
aktblob = startblob; |
|||
while(aktblob){ |
|||
retval = updateBlob(aktblob); |
|||
if(!retval){ |
|||
nextblob = aktblob->next; |
|||
}else if(retval == 1){ |
|||
if(aktblob == startblob){ |
|||
startblob = aktblob->next; |
|||
}else{ |
|||
aktblob->last->next = aktblob->next; |
|||
} |
|||
if(aktblob->next){ |
|||
aktblob->next->last = aktblob->last; |
|||
} |
|||
nextblob = aktblob->next; |
|||
free(aktblob); |
|||
}else if(retval == 2){ |
|||
blob_t * newblob = setupBlob(0); |
|||
if (newblob){ |
|||
newblob->last = aktblob; |
|||
newblob->next = aktblob->next; |
|||
if(aktblob->next){ |
|||
aktblob->next->last = newblob; |
|||
} |
|||
aktblob->next = newblob; |
|||
} |
|||
nextblob = aktblob->next; |
|||
} |
|||
aktblob = nextblob; |
|||
} |
|||
|
|||
aktblob = startblob; |
|||
clear_text_pixmap(0); |
|||
while(aktblob){ |
|||
drawBlob(aktblob); |
|||
aktblob = aktblob->next; |
|||
} |
|||
update_pixmap(); |
|||
wait(2); |
|||
}; |
|||
startblob = setupBlob(0); |
|||
//showBlob(startblob);
|
|||
}while(startblob); |
|||
|
|||
exit: |
|||
free(text_pixmap); |
|||
memcpy (newmode_jmpbuf, tmp_jmpbuf, sizeof(jmp_buf)); |
|||
} |
@ -0,0 +1,111 @@ |
|||
PRG = borgSim |
|||
OPTIMIZE = -O0 |
|||
LIBS = -lglut -lpthread -lGL -lGLU |
|||
CC = gcc |
|||
LD = ld |
|||
|
|||
override CFLAGS = -g -Wall -pedantic -std=c99 $(OPTIMIZE) |
|||
$(DEFS) |
|||
override LDFLAGS = -Wl,-Map,$(PRG).map |
|||
|
|||
OBJ = breakpoint.o font_arial8.o font_small6.o font_uni53.o invader_draw.o \
|
|||
invader_init.o invader_proc.o invaders2.o joystick.o main.o menu.o pixel.o \
|
|||
programm.o scrolltext3.o snake.o trackball.o util.o tetris/input.o \
|
|||
tetris/logic.o tetris/piece.o tetris/playfield.o tetris/view.o prng.o \
|
|||
memxor_c.o noekeon.o stonefly.o |
|||
|
|||
all: $(PRG) |
|||
|
|||
$(PRG): $(OBJ) |
|||
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJ) -o $@ |
|||
|
|||
clean: |
|||
rm -rf $(OBJ) $(PRG) $(PRG).map |
|||
|
|||
breakpoint.o: breakpoint.c pixel.h util.h config.h |
|||
$(CC) $(CFLAGS) -c -o breakpoint.o breakpoint.c |
|||
|
|||
font_arial8.o: font_arial8.c font.h |
|||
$(CC) $(CFLAGS) -c -o font_arial8.o font_arial8.c |
|||
|
|||
font_small6.o: font_small6.c font.h |
|||
$(CC) $(CFLAGS) -c -o font_small6.o font_small6.c |
|||
|
|||
font_uni53.o: font_uni53.c font.h |
|||
$(CC) $(CFLAGS) -c -o font_uni53.o font_uni53.c |
|||
|
|||
invader_draw.o: invader_draw.c invaders2.h pixel.h util.h config.h \ |
|||
scrolltext.h joystick.h |
|||
$(CC) $(CFLAGS) -c -o invader_draw.o invader_draw.c |
|||
|
|||
invader_init.o: invader_init.c invaders2.h pixel.h util.h config.h \ |
|||
scrolltext.h joystick.h |
|||
$(CC) $(CFLAGS) -c -o invader_init.o invader_init.c |
|||
|
|||
invader_proc.o: invader_proc.c invaders2.h pixel.h util.h config.h \ |
|||
scrolltext.h joystick.h |
|||
$(CC) $(CFLAGS) -c -o invader_proc.o invader_proc.c |
|||
|
|||
invaders2.o: invaders2.c util.h invaders2.h pixel.h config.h scrolltext.h \ |
|||
joystick.h |
|||
$(CC) $(CFLAGS) -c -o invaders2.o invaders2.c |
|||
|
|||
joystick.o: joystick.c joystick.h |
|||
$(CC) $(CFLAGS) -c -o joystick.o joystick.c |
|||
|
|||
main.o: main.c config.h pixel.h util.h programm.h menu.h tetris/logic.h \ |
|||
tetris/piece.h trackball.h snake.h scrolltext.h |
|||
$(CC) $(CFLAGS) -c -o main.o main.c |
|||
|
|||
menu.o: menu.c menu.h config.h util.h pixel.h joystick.h snake.h \ |
|||
tetris/logic.h tetris/piece.h invaders2.h scrolltext.h |
|||
$(CC) $(CFLAGS) -c -o menu.o menu.c |
|||
|
|||
pixel.o: pixel.c pixel.h util.h config.h |
|||
$(CC) $(CFLAGS) -c -o pixel.o pixel.c |
|||
|
|||
programm.o: programm.c pixel.h util.h config.h programm.h joystick.h |
|||
$(CC) $(CFLAGS) -c -o programm.o programm.c |
|||
|
|||
scrolltext3.o: scrolltext3.c config.h scrolltext.h pixel.h util.h \ |
|||
font_arial8.h font.h font_small6.h font_uni53.h |
|||
$(CC) $(CFLAGS) -c -o scrolltext3.o scrolltext3.c |
|||
|
|||
snake.o: snake.c pixel.h util.h config.h joystick.h |
|||
$(CC) $(CFLAGS) -c -o snake.o snake.c |
|||
|
|||
trackball.o: trackball.c trackball.h |
|||
$(CC) $(CFLAGS) -c -o trackball.o trackball.c |
|||
|
|||
util.o: util.c joystick.h |
|||
$(CC) $(CFLAGS) -c -o util.o util.c |
|||
|
|||
noekeon.o: noekeon.c noekeon.h memxor.h |
|||
$(CC) $(CFLAGS) -c -o $@ $< |
|||
|
|||
memxor_c.o: memxor_c.c memxor.h |
|||
$(CC) $(CFLAGS) -c -o $@ $< |
|||
|
|||
prng.o: prng.c prng.h noekeon.h memxor.h |
|||
$(CC) $(CFLAGS) -c -o $@ $< |
|||
|
|||
tetris/input.o: tetris/input.c joystick.h util.h tetris/input.h |
|||
$(CC) $(CFLAGS) -c -o tetris/input.o tetris/input.c |
|||
|
|||
logic.o: tetris/logic.c tetris/logic.h tetris/piece.h tetris/playfield.h \ |
|||
tetris/view.h tetris/input.h prng.h ../borg-base/prng.h |
|||
$(CC) $(CFLAGS) -c -o tetris/logic.o tetris/logic.c |
|||
|
|||
tetris/piece.o: tetris/piece.c tetris/piece.h |
|||
$(CC) $(CFLAGS) -c -o tetris/piece.o tetris/piece.c |
|||
|
|||
tetris/playfield.o: tetris/playfield.c tetris/playfield.h tetris/piece.h |
|||
$(CC) $(CFLAGS) -c -o tetris/playfield.o tetris/playfield.c |
|||
|
|||
tetris/view.o: tetris/view.c config.h pixel.h util.h scrolltext.h \ |
|||
tetris/logic.h tetris/piece.h tetris/playfield.h tetris/view.h |
|||
$(CC) $(CFLAGS) -c -o tetris/view.o tetris/view.c |
|||
|
|||
stonefly.o: stonefly.h stonefly.c pixel.h util.h config.h prng.h \ |
|||
../borg-base/prng.h tetris/piece.h |
|||
$(CC) $(CFLAGS) -c -o stonefly.o stonefly.c |
@ -0,0 +1,102 @@ |
|||
PRG = borgSim |
|||
APP = $(PRG).app/Contents/MacOS/$(PRG) |
|||
OPTIMIZE = -O2 |
|||
LIBS = -lpthread -framework Carbon -framework GLUT -framework OpenGL -framework Foundation -framework AppKit |
|||
CC = gcc |
|||
LD = ld |
|||
|
|||
override CFLAGS = -g -Wall -pedantic -std=c99 $(OPTIMIZE) -DOSX_ |
|||
$(DEFS) |
|||
override LDFLAGS = -Wl --prebind |
|||
|
|||
OBJ = breakpoint.o font_arial8.o font_small6.o font_uni53.o invader_draw.o \
|
|||
invader_init.o invader_proc.o invaders2.o joystick.o main.o menu.o pixel.o \
|
|||
programm.o scrolltext3.o snake.o trackball.o util.o tetris/input.o \
|
|||
tetris/logic.o tetris/piece.o tetris/playfield.o tetris/view.o |
|||
|
|||
all: Makefile.osx $(APP) |
|||
|
|||
$(APP): $(OBJ) |
|||
test -d $(PRG).app/Contents/MacOS/ || mkdir -p $(PRG).app/Contents/MacOS/ |
|||
test -d $(PRG).app/Contents/Resources/ || mkdir -p $(PRG).app/Resources/ |
|||
test $(PRG).app/Contents/Rescources/borg3d.icns || cp -f borg3d.icns $(PRG).app/Contents/Rescources/ |
|||
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJ) -o $@ |
|||
|
|||
clean: |
|||
rm -rf $(OBJ) $(PRG) $(PRG).app/ |
|||
|
|||
breakpoint.o: breakpoint.c pixel.h util.h config.h |
|||
$(CC) $(CFLAGS) -c -o breakpoint.o breakpoint.c |
|||
|
|||
font_arial8.o: font_arial8.c font.h |
|||
$(CC) $(CFLAGS) -c -o font_arial8.o font_arial8.c |
|||
|
|||
font_small6.o: font_small6.c font.h |
|||
$(CC) $(CFLAGS) -c -o font_small6.o font_small6.c |
|||
|
|||
font_uni53.o: font_uni53.c font.h |
|||
$(CC) $(CFLAGS) -c -o font_uni53.o font_uni53.c |
|||
|
|||
invader_draw.o: invader_draw.c invaders2.h pixel.h util.h config.h \ |
|||
scrolltext.h joystick.h |
|||
$(CC) $(CFLAGS) -c -o invader_draw.o invader_draw.c |
|||
|
|||
invader_init.o: invader_init.c invaders2.h pixel.h util.h config.h \ |
|||
scrolltext.h joystick.h |
|||
$(CC) $(CFLAGS) -c -o invader_init.o invader_init.c |
|||
|
|||
invader_proc.o: invader_proc.c invaders2.h pixel.h util.h config.h \ |
|||
scrolltext.h joystick.h |
|||
$(CC) $(CFLAGS) -c -o invader_proc.o invader_proc.c |
|||
|
|||
invaders2.o: invaders2.c util.h invaders2.h pixel.h config.h scrolltext.h \ |
|||
joystick.h |
|||
$(CC) $(CFLAGS) -c -o invaders2.o invaders2.c |
|||
|
|||
joystick.o: joystick.c joystick.h |
|||
$(CC) $(CFLAGS) -c -o joystick.o joystick.c |
|||
|
|||
main.o: main.c config.h pixel.h util.h programm.h menu.h tetris/logic.h \ |
|||
tetris/piece.h trackball.h snake.h scrolltext.h |
|||
$(CC) $(CFLAGS) -c -o main.o main.c |
|||
|
|||
menu.o: menu.c menu.h config.h util.h pixel.h joystick.h snake.h \ |
|||
tetris/logic.h tetris/piece.h invaders2.h scrolltext.h |
|||
$(CC) $(CFLAGS) -c -o menu.o menu.c |
|||
|
|||
pixel.o: pixel.c pixel.h util.h config.h |
|||
$(CC) $(CFLAGS) -c -o pixel.o pixel.c |
|||
|
|||
programm.o: programm.c pixel.h util.h config.h programm.h joystick.h |
|||
$(CC) $(CFLAGS) -c -o programm.o programm.c |
|||
|
|||
scrolltext3.o: scrolltext3.c config.h scrolltext.h pixel.h util.h \ |
|||
font_arial8.h font.h font_small6.h font_uni53.h |
|||
$(CC) $(CFLAGS) -c -o scrolltext3.o scrolltext3.c |
|||
|
|||
snake.o: snake.c pixel.h util.h config.h joystick.h |
|||
$(CC) $(CFLAGS) -c -o snake.o snake.c |
|||
|
|||
trackball.o: trackball.c trackball.h |
|||
$(CC) $(CFLAGS) -c -o trackball.o trackball.c |
|||
|
|||
util.o: util.c joystick.h |
|||
$(CC) $(CFLAGS) -c -o util.o util.c |
|||
|
|||
tetris/input.o: tetris/input.c joystick.h util.h tetris/input.h |
|||
$(CC) $(CFLAGS) -c -o tetris/input.o tetris/input.c |
|||
|
|||
tetris/logic.o: tetris/logic.c tetris/logic.h tetris/piece.h \ |
|||
tetris/playfield.h tetris/view.h tetris/input.h |
|||
$(CC) $(CFLAGS) -c -o tetris/logic.o tetris/logic.c |
|||
|
|||
tetris/piece.o: tetris/piece.c tetris/piece.h |
|||
$(CC) $(CFLAGS) -c -o tetris/piece.o tetris/piece.c |
|||
|
|||
tetris/playfield.o: tetris/playfield.c tetris/playfield.h tetris/piece.h |
|||
$(CC) $(CFLAGS) -c -o tetris/playfield.o tetris/playfield.c |
|||
|
|||
tetris/view.o: tetris/view.c config.h pixel.h util.h scrolltext.h \ |
|||
tetris/logic.h tetris/piece.h tetris/playfield.h tetris/view.h |
|||
$(CC) $(CFLAGS) -c -o tetris/view.o tetris/view.c |
|||
|
@ -0,0 +1,309 @@ |
|||
|
|||
|
|||
#ifdef _WIN32 |
|||
# include <GL/glut.h> |
|||
# include <windows.h> |
|||
# include <process.h> |
|||
# define pthread_t int |
|||
#else |
|||
# ifdef OSX_ |
|||
# include <GLUT/glut.h> |
|||
# else |
|||
# include <GL/glut.h> |
|||
# endif |
|||
# include <pthread.h> // for threads in linux
|
|||
# include <stdlib.h> |
|||
# include <sys/time.h> |
|||
# include <sys/types.h> |
|||
# include <unistd.h> |
|||
#endif |
|||
|
|||
#include <stdio.h> |
|||
#include <setjmp.h> |
|||
#include "config.h" |
|||
#include "pixel.h" |
|||
#include "programm.h" |
|||
#include "menu.h" |
|||
#include "tetris/logic.h" |
|||
#include "trackball.h" |
|||
#include "snake.h" |
|||
#include "stonefly.h" |
|||
|
|||
#include "scrolltext.h" |
|||
|
|||
|
|||
|
|||
unsigned char fakeport; |
|||
jmp_buf newmode_jmpbuf; |
|||
volatile unsigned char oldMode, oldOldmode, mode; |
|||
extern unsigned char waitForFire; |
|||
|
|||
|
|||
int WindWidth, WindHeight; |
|||
|
|||
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; |
|||
unsigned char joystick; |
|||
|
|||
float view_rotx = 0, view_roty = 0, view_rotz = 0; |
|||
int win; |
|||
|
|||
|
|||
pthread_t simthread; |
|||
GLUquadric* quad; |
|||
|
|||
void drawLED(int color, float pos_x, float pos_y, float pos_z) { |
|||
glPushMatrix(); |
|||
glTranslatef(pos_x, pos_y, pos_z); |
|||
glCallList(color); |
|||
glPopMatrix(); |
|||
} |
|||
|
|||
void display(void){ |
|||
int x, y, z, level, color; |
|||
tbReshape(WindWidth, WindHeight); |
|||
glClear(GL_COLOR_BUFFER_BIT); |
|||
glPushMatrix(); |
|||
glTranslatef(NUM_COLS*2., 0., NUM_ROWS*2.); |
|||
tbMatrix(); |
|||
glRotatef(view_rotx, 1.0, 0.0, 0.0); |
|||
glRotatef(view_roty, 0.0, 1.0, 0.0); |
|||
glRotatef(view_rotz, 0.0, 0.0, 1.0); |
|||
glTranslatef(-NUM_COLS*2, 0., -NUM_ROWS*2.); |
|||
for (x = 0; x < 1; x++) { |
|||
for (y = 0; y < NUM_COLS; y++) { |
|||
for (z = 0; z < NUM_ROWS; z++) { |
|||
color = 0; |
|||
for (level = 0; level < NUMPLANE; level++) { |
|||
if (pixmap[level][z%NUM_ROWS][y/8] & (1 << y % 8)) { |
|||
color = level+1; |
|||
} |
|||
} |
|||
drawLED(color, (float)y*4.0, |
|||
(float)x*4.0, |
|||
(float)(NUM_ROWS-1-z)*4.0); |
|||
} |
|||
} |
|||
} |
|||
glPopMatrix(); |
|||
glutSwapBuffers(); |
|||
#ifdef _WIN32 |
|||
Sleep(10); |
|||
#else |
|||
usleep(20000); |
|||
#endif |
|||
joystick = 255; |
|||
} |
|||
|
|||
void keyboard(unsigned char key, int x, int y){ |
|||
switch (key) { |
|||
case 'q': printf("Quit\n"); |
|||
glutDestroyWindow(win); |
|||
exit(0); |
|||
break; |
|||
case ' ': |
|||
fakeport |= 0x01; |
|||
break; |
|||
case 'a': |
|||
fakeport |= 0x02; |
|||
break; |
|||
case 'd': |
|||
fakeport |= 0x04; |
|||
break; |
|||
case 's': |
|||
fakeport |= 0x08; |
|||
break; |
|||
case 'w': |
|||
fakeport |= 0x10; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void keyboardup(unsigned char key, int x, int y){ |
|||
switch (key) { |
|||
case ' ': |
|||
fakeport &= ~0x01; |
|||
break; |
|||
case 'a': |
|||
fakeport &= ~0x02; |
|||
break; |
|||
case 'd': |
|||
fakeport &= ~0x04; |
|||
break; |
|||
case 's': |
|||
fakeport &= ~0x08; |
|||
break; |
|||
case 'w': |
|||
fakeport &= ~0x10; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void mouse(int button, int state, int x, int y) |
|||
{ |
|||
tbMouse(button, state, x, y); |
|||
} |
|||
|
|||
void motion(int x, int y) |
|||
{ |
|||
tbMotion(x, y); |
|||
} |
|||
|
|||
void reshape(int width, int height) |
|||
{ |
|||
|
|||
tbReshape(width, height); |
|||
|
|||
glViewport(0, 0, width, height); |
|||
|
|||
glMatrixMode(GL_PROJECTION); |
|||
glLoadIdentity(); |
|||
gluPerspective(60.0, (float)WindWidth/(float)WindWidth, 5., 1000.); |
|||
gluLookAt(NUM_ROWS*2., NUM_ROWS*2.+50., NUM_COLS*2., |
|||
NUM_ROWS*2., NUM_ROWS*2., NUM_COLS*2., |
|||
0.0, 0.0, 1.0); |
|||
glMatrixMode(GL_MODELVIEW); |
|||
glLoadIdentity(); |
|||
|
|||
WindWidth = width; |
|||
WindHeight = height; |
|||
} |
|||
|
|||
/* change view angle */ |
|||
static void special(int k, int x, int y) { |
|||
switch (k) { |
|||
case GLUT_KEY_UP: |
|||
view_rotx += 5.0; |
|||
break; |
|||
case GLUT_KEY_DOWN: |
|||
view_rotx -= 5.0; |
|||
break; |
|||
case GLUT_KEY_LEFT: |
|||
view_rotz += 5.0; |
|||
break; |
|||
case GLUT_KEY_RIGHT: |
|||
view_rotz -= 5.0; |
|||
break; |
|||
default: |
|||
return; |
|||
} |
|||
glutPostRedisplay(); |
|||
} |
|||
/*
|
|||
void timf(int value) { |
|||
glutPostRedisplay(); |
|||
glutTimerFunc(1, timf, 0); |
|||
}*/ |
|||
|
|||
void *display_loop(void * unused) { |
|||
unsigned char mode;;; |
|||
mode = setjmp(newmode_jmpbuf); |
|||
oldOldmode = oldMode; |
|||
waitForFire = 1; |
|||
scrolltext("</#Scrolltext3 Test"); |
|||
for(;;){ |
|||
oldMode = mode; |
|||
switch(mode++) { |
|||
case 1: |
|||
stonefly(); |
|||
break; |
|||
case 2: |
|||
breakpoint(); |
|||
break; |
|||
case 3: |
|||
schwarzesLoch(); |
|||
break; |
|||
case 4: |
|||
scrolltext("</#Scrolltext3 Test"); |
|||
break; |
|||
case 5: |
|||
spirale(20); |
|||
break; |
|||
case 6: |
|||
joern1(); |
|||
break; |
|||
case 7: |
|||
snake(); |
|||
break; |
|||
case 8: |
|||
schachbrett(20); |
|||
break; |
|||
case 9: |
|||
feuer(); |
|||
break; |
|||
case 10: |
|||
matrix(); |
|||
break; |
|||
case 31: |
|||
fadein(); |
|||
break; |
|||
case 32: |
|||
test1(); |
|||
break; |
|||
case 43: |
|||
menu(); |
|||
mode = oldOldmode; |
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
int main(int argc, char **argv){ |
|||
WindHeight = 700; |
|||
WindWidth = 700; |
|||
glutInit(&argc,argv); |
|||
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); |
|||
glutInitWindowSize(WindHeight, WindWidth); |
|||
win = glutCreateWindow("16x16 Borg Simulator"); |
|||
|
|||
// callback
|
|||
//glutReshapeFunc(reshape);
|
|||
glutDisplayFunc(display); |
|||
glutIdleFunc(display); |
|||
glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF); |
|||
glutKeyboardFunc(keyboard); |
|||
glutKeyboardUpFunc(keyboardup); |
|||
glutSpecialFunc(special); |
|||
glutMouseFunc(mouse); |
|||
glutMotionFunc(motion); |
|||
|
|||
// clearcolor & main loop
|
|||
glClearColor(0,0,0,1.0); |
|||
gluPerspective(60.0, (float)WindWidth/(float)WindWidth, 5., 1000.); |
|||
gluLookAt(NUM_COLS*2., NUM_COLS*2.+50., NUM_ROWS*2., |
|||
NUM_COLS*2., NUM_COLS*2., NUM_ROWS*2., |
|||
0.0, 0.0, 1.0); |
|||
|
|||
// init Call List for LED
|
|||
quad = gluNewQuadric(); |
|||
glNewList(0, GL_COMPILE); |
|||
glColor4f(0.8, 0.0, 0.0, 1.); |
|||
gluSphere(quad, 1.0, 12, 12); |
|||
glEndList(); |
|||
glNewList(1, GL_COMPILE); |
|||
glColor4f(0.5, 0.0, 0.0, 1.); |
|||
gluSphere(quad, 1.4, 12, 12); |
|||
glEndList(); |
|||
glNewList(2, GL_COMPILE); |
|||
glColor4f(0.7, 0.0, 0.0, 1.); |
|||
gluSphere(quad, 1.55, 12, 12); |
|||
glEndList(); |
|||
glNewList(3, GL_COMPILE); |
|||
glColor4f(1.00, 0.0, 0.0, 1.); |
|||
gluSphere(quad, 1.7, 12, 12); |
|||
glEndList(); |
|||
|
|||
tbInit(GLUT_LEFT_BUTTON); |
|||
tbAnimate(GL_FALSE); |
|||
|
|||
// start display_loop thread
|
|||
#ifdef _WIN32 |
|||
_beginthread((void (*)(void*))display_loop, 0, NULL); |
|||
#else |
|||
pthread_create(&simthread, NULL, display_loop, NULL); |
|||
#endif |
|||
//glutTimerFunc(40, timf, 0); // Set up timer for 40ms, about 25 fps
|
|||
glutMainLoop(); |
|||
return 0; |
|||
} |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue