renamed project because it is to cool for stupid name
This commit is contained in:
commit
fe14b29d15
|
@ -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,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,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
Load Diff
|
@ -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 have changed in this diff Show More
Loading…
Reference in New Issue