saved up to 240 bytes (depending on borg hw), translated some German comments into English and cleaned up formatting (sorry about the noise)

This commit is contained in:
Christian Kroll 2011-08-17 01:16:25 +00:00
parent 3e8768866c
commit d4ae78fee3
13 changed files with 784 additions and 876 deletions

View File

@ -128,31 +128,13 @@ static uint8_t amphibian_getChunk(unsigned char const nBitPlane,
{0x06, 0x30, 0xC6}, {0x06, 0x30, 0xC6},
{0x07, 0xF0, 0xFE}}}; {0x07, 0xF0, 0xFE}}};
static uint8_t const nOffsetTable[] PROGMEM =
{UINT8_MAX, 0, 4, 8, 12, 8, 4, 0};
uint8_t const nOffset = pgm_read_byte(&nOffsetTable[(nFrame >> 1) % 8]);
if ((nChunkX <= 2) && (nChunkY >= 2) && (nChunkY <= 5) if ((nChunkX <= 2) && (nChunkY >= 2) && (nChunkY <= 5)
&& (((nFrame >> 1) % 8) != 0)) && (nOffset != UINT8_MAX))
{ {
uint8_t nOffset;
switch ((nFrame >> 1) % 8)
{
case 1:
case 7:
nOffset = 0;
break;
case 2:
case 6:
nOffset = 4;
break;
case 3:
case 5:
nOffset = 8;
break;
case 4:
default:
nOffset = 12;
break;
}
return pgm_read_byte(&aEye[nBitPlane][nChunkY-2+nOffset][nChunkX]); return pgm_read_byte(&aEye[nBitPlane][nChunkY-2+nOffset][nChunkX]);
} }
else else

View File

@ -106,7 +106,7 @@ typedef uint8_t field_t[FIELD_YSIZE][FIELD_XSIZE];
/******************************************************************************/ /******************************************************************************/
void setcell(field_t pf, coord_t x, coord_t y, cell_t value) { static void setcell(field_t pf, coord_t x, coord_t y, cell_t value) {
if (value != dead) { if (value != dead) {
pf[y][x / 8] |= shl_table[x & 7]; pf[y][x / 8] |= shl_table[x & 7];
} else { } else {
@ -144,25 +144,23 @@ void nextiteration(field_t dest, field_t src) {
uint8_t tc; uint8_t tc;
for (y = YSIZE; y--;) { for (y = YSIZE; y--;) {
for (x = XSIZE; x--;) { for (x = XSIZE; x--;) {
cell_t cell;
tc = countsurroundingalive(src, x, y); tc = countsurroundingalive(src, x, y);
switch (tc) { switch (tc) {
// case 0:
// case 1:
// /* dead */
// setcell(dest, x,y, dead);
case 2: case 2:
/* keep */ /* keep */
setcell(dest, x, y, getcell(src, x, y)); continue;
break; break;
case 3: case 3:
/* alive */ /* alive */
setcell(dest, x, y, alive); cell = alive;
break; break;
default: default:
/* dead */ /* dead */
setcell(dest, x, y, dead); cell = dead;
break; break;
} }
setcell(dest, x, y, cell);
} }
} }
} }

View File

@ -1,8 +1,7 @@
#ifndef BORG_HW_H #ifndef BORG_HW_H
#define BORG_HW_H #define BORG_HW_H
//Linebytes gibt die Zahl der Bytes pro Zeile in der // LINEBYTES holds the amount of bytes per line within the framebuffer (pixmap)
//Pixmap an, also Spaltenzahl/8 aufgerundet
#define LINEBYTES (((NUM_COLS-1)/8)+1) #define LINEBYTES (((NUM_COLS-1)/8)+1)

View File

@ -1,4 +1,3 @@
#include "../config.h" #include "../config.h"
#include "../makros.h" #include "../makros.h"
@ -8,25 +7,27 @@
#include "borg_hw.h" #include "borg_hw.h"
/* /*
// Diese #defines werden nun durch menuconfig gesetzt // those macros get defined via menuconfig, now
// 16 Spalten insgesamt direkt gesteuert, dafür 2 Ports // 16 columns total directly controlled, therefore 2 ports
#define COLPORT1 PORTA #define COLPORT1 PORTA
#define COLDDR1 DDRA #define COLDDR1 DDRA
#define COLPORT2 PORTC #define COLPORT2 PORTC
#define COLDDR2 DDRC #define COLDDR2 DDRC
// Der andere Port übernimmt die Steuerung der Schieberegister // the other port controls the shift registers
#define ROWPORT PORTD #define ROWPORT PORTD
#define ROWDDR DDRD #define ROWDDR DDRD
// Clock und reset gehen gemeinsam an beide Schieberegister
// der reset pin ist negiert // both clock and reset are connected to each shift register
#define PIN_MCLR PD4 // reset pin is negated
#define PIN_CLK PD5 #define PIN_MCLR PD4
//das dier sind die individuellen Dateneingänge für die Schieberegister #define PIN_CLK PD5
#define PIN_DATA1 PD6
#define PIN_DATA2 PD7 // these are the individual data input pins for the shift registers
#define PIN_DATA1 PD6
#define PIN_DATA2 PD7
*/ */
#define COLDDR1 DDR(COLPORT1) #define COLDDR1 DDR(COLPORT1)
@ -39,90 +40,80 @@
#define SIG_OUTPUT_COMPARE0 SIG_OUTPUT_COMPARE0A #define SIG_OUTPUT_COMPARE0 SIG_OUTPUT_COMPARE0A
#endif #endif
// buffer which holds the currently shown frame
//Der Puffer, in dem das aktuelle Bild gespeichert wird
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
// display a row
//Eine Zeile anzeigen static void rowshow(unsigned char row, unsigned char plane) {
inline void rowshow(unsigned char row, unsigned char plane){ //reset states of preceding row
//Die Zustände von der vorherigen Zeile löschen
COLPORT1 = 0; COLPORT1 = 0;
COLPORT2 = 0; COLPORT2 = 0;
//kurze Warteschleife, damit die Treiber auch wirklich ausschalten // short delay loop, to ensure proper deactivation of the drivers
unsigned char i; unsigned char i;
for(i=0;i<20;i++){ for (i = 0; i < 20; i++) {
asm volatile("nop"); asm volatile("nop");
} }
if (row == 0) {
if (row == 0){ // row 0: initialize first shift register
//Zeile 0: Das erste Schieberegister initialisieren ROWPORT &= ~(1 << PIN_MCLR);
ROWPORT&= ~(1<<PIN_MCLR); ROWPORT |= (1 << PIN_MCLR);
ROWPORT|= (1<<PIN_MCLR); ROWPORT |= (1 << PIN_DATA1);
ROWPORT|= (1<<PIN_DATA1); ROWPORT |= (1 << PIN_CLK);
ROWPORT|= (1<<PIN_CLK); ROWPORT &= ~(1 << PIN_CLK);
ROWPORT&= ~(1<<PIN_CLK); ROWPORT &= ~(1 << PIN_DATA1);
ROWPORT&= ~(1<<PIN_DATA1);
// depending on the currently drawn plane, display the row for a
//Je nachdem, welche der Ebenen wir Zeichnen, die Zeile verschieden lange Anzeigen // specific amount of time
switch (plane){ static unsigned char const ocr0_table[] = {5, 8, 20};
case 0: OCR0 = ocr0_table[plane];
OCR0 = 5; } else if (row == 8) {
break; // row 8: initialize second shift register
case 1: ROWPORT &= ~(1 << PIN_MCLR);
OCR0 = 8; ROWPORT |= (1 << PIN_MCLR);
break; ROWPORT |= (1 << PIN_DATA2);
case 2: ROWPORT |= (1 << PIN_CLK);
OCR0 = 20; ROWPORT &= ~(1 << PIN_CLK);
} ROWPORT &= ~(1 << PIN_DATA2);
}else if(row == 8){ } else {
//Zeile 8: Das Zweite Schieberegister initialisieren // remaining rows: just shift forward
ROWPORT&= ~(1<<PIN_MCLR); ROWPORT |= (1 << PIN_CLK);
ROWPORT|= (1<<PIN_MCLR); ROWPORT &= ~(1 << PIN_CLK);
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 // another delay loop, to ensure that the drivers are ready
for(i=0;i<20;i++){ for (i = 0; i < 20; i++) {
asm volatile("nop"); asm volatile("nop");
} }
//die Daten für die aktuelle Zeile auf die Spaltentreiber ausgeben // output data of the current row to the column drivers
COLPORT1 = pixmap[plane][row][0]; COLPORT1 = pixmap[plane][row][0];
COLPORT2 = pixmap[plane][row][1]; COLPORT2 = pixmap[plane][row][1];
} }
// depending on the plane this interrupt gets triggered at 50 kHz, 31.25 kHz or
//Dieser Interrupt wird je nach Ebene mit 50kHz 31,25kHz oder 12,5kHz ausgeführt // 12.5 kHz
SIGNAL(SIG_OUTPUT_COMPARE0) SIGNAL(SIG_OUTPUT_COMPARE0) {
{
static unsigned char plane = 0; static unsigned char plane = 0;
static unsigned char row = 0; static unsigned char row = 0;
//Watchdog zurücksetzen // reset watchdog
wdt_reset(); wdt_reset();
//Die aktuelle Zeile in der aktuellen Ebene ausgeben // output current row according to current plane
rowshow(row, plane); rowshow(row, plane);
//Zeile und Ebene inkrementieren // increment both row and plane
if(++row == NUM_ROWS){ if (++row == NUM_ROWS) {
row = 0; row = 0;
if(++plane==NUMPLANE) plane=0; if (++plane == NUMPLANE) {
plane = 0;
}
} }
} }
void timer0_off() {
void timer0_off(){
cli(); cli();
COLPORT1 = 0; COLPORT1 = 0;
@ -130,60 +121,58 @@ void timer0_off(){
ROWPORT = 0; ROWPORT = 0;
#ifdef __AVR_ATmega644P__ #ifdef __AVR_ATmega644P__
TCCR0A = 0x00; TCCR0A = 0x00;
TCCR0B = 0x00; TCCR0B = 0x00;
#else #else
TCCR0 = 0x00; TCCR0 = 0x00;
#endif #endif
sei(); sei();
} }
// initialize timer which triggers the interrupt
// Den Timer, der denn Interrupt auslöst, initialisieren static void timer0_on() {
void timer0_on(){ /* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00 CS02 CS01 CS00
CS02 CS01 CS00 0 0 0 stop
0 0 0 stop 0 0 1 clk
0 0 1 clk 0 1 0 clk/8
0 1 0 clk/8 0 1 1 clk/64
0 1 1 clk/64 1 0 0 clk/256
1 0 0 clk/256 1 0 1 clk/1024
1 0 1 clk/1024 */
*/
#ifdef __AVR_ATmega644P__ #ifdef __AVR_ATmega644P__
TCCR0A = 0x02; // CTC Mode TCCR0A = 0x02; // CTC Mode
TCCR0B = 0x03; // clk/64 TCCR0B = 0x03; // clk/64
TCNT0 = 0; // reset timer TCNT0 = 0; // reset timer
OCR0 = 20; // Compare with this value OCR0 = 20; // compare with this value
TIMSK0 = 0x02; // Compare match Interrupt on TIMSK0 = 0x02; // compare match Interrupt on
#else #else
TCCR0 = 0x0B; // CTC Mode, clk/64 TCCR0 = 0x0B; // CTC Mode, clk/64
TCNT0 = 0; // reset timer TCNT0 = 0; // reset timer
OCR0 = 20; // Compare with this value OCR0 = 20; // compare with this value
TIMSK = 0x02; // Compare match Interrupt on TIMSK = 0x02; // compare match Interrupt on
#endif #endif
} }
void borg_hw_init(){ void borg_hw_init() {
//Spalten Ports auf Ausgang // switch column ports to output mode
COLDDR1 = 0xFF; COLDDR1 = 0xFF;
COLDDR2 = 0xFF; COLDDR2 = 0xFF;
//Pins am Zeilenport auf Ausgang // switch pins of the row port to output mode
ROWDDR = (1<<PIN_MCLR) | (1<<PIN_CLK) | (1<< PIN_DATA1) | (1<<PIN_DATA2); ROWDDR = (1<<PIN_MCLR) | (1<<PIN_CLK) | (1<<PIN_DATA1) | (1<<PIN_DATA2);
//Alle Spalten erstmal aus // switch off all columns for now
COLPORT1 = 0; COLPORT1 = 0;
COLPORT2 = 0; COLPORT2 = 0;
//Schieberegister für Zeilen zurücksetzen // reset shift registers for the rows
ROWPORT = 0; ROWPORT = 0;
timer0_on(); timer0_on();
//Watchdog Timer aktivieren // activate watchdog timer
wdt_reset(); wdt_reset();
wdt_enable(0x00); // 17ms Watchdog wdt_enable(0x00); // 17ms watchdog
} }

View File

@ -1,4 +1,3 @@
#include "../config.h" #include "../config.h"
#include "../makros.h" #include "../makros.h"
@ -8,24 +7,26 @@
#include "borg_hw.h" #include "borg_hw.h"
/* /*
// Diese #defines werden nun durch menuconfig gesetzt // those macros get defined via menuconfig, now
// 16 Spalten insgesamt direkt gesteuert, dafür 2 Ports // 16 columns total directly controlled, therefore 2 ports
#define COLPORT1 PORTC #define COLPORT1 PORTC
#define COLDDR1 DDRC #define COLDDR1 DDRC
#define COLPORT2 PORTA #define COLPORT2 PORTA
#define COLDDR2 DDRA #define COLDDR2 DDRA
// Der andere Port übernimmt die Steuerung der Schieberegister // the other port controls the shift registers
#define ROWPORT PORTD #define ROWPORT PORTD
#define ROWDDR DDRD #define ROWDDR DDRD
// Clock und reset gehen gemeinsam an beide Schieberegister
// der reset pin ist negiert // both clock and reset are connected to each shift register
#define PIN_MCLR PD4 // reset pin is negated
#define PIN_CLK PD6 #define PIN_MCLR PD4
//das dier sind die individuellen Dateneingänge für die Schieberegister #define PIN_CLK PD6
#define PIN_DATA PD7
// these are the individual data input pins for the shift registers
#define PIN_DATA PD7
*/ */
#define COLDDR1 DDR(COLPORT1) #define COLDDR1 DDR(COLPORT1)
@ -38,33 +39,30 @@
#define SIG_OUTPUT_COMPARE0 SIG_OUTPUT_COMPARE0A #define SIG_OUTPUT_COMPARE0 SIG_OUTPUT_COMPARE0A
#endif #endif
// buffer which holds the currently shown frame
//Der Puffer, in dem das aktuelle Bild gespeichert wird
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
// switch to next row
//zur nächsten Zeile weiterschalten static void nextrow(uint8_t row) {
inline void nextrow(uint8_t row){ //reset states of preceding row
//Die Zustände von der vorherigen Zeile löschen
COLPORT1 = 0; COLPORT1 = 0;
COLPORT2 = 0; COLPORT2 = 0;
//kurze Warteschleife, damit die Treiber auch wirklich ausschalten // short delay loop, to ensure proper deactivation of the drivers
unsigned char i; unsigned char i;
for(i=0;i<10;i++){ for (i = 0; i < 10; i++) {
asm volatile("nop"); asm volatile("nop");
} }
if (row == 0){ if (row == 0) {
//Zeile 0: Das erste Schieberegister initialisieren // row 0: initialize first shift register
#ifndef INVERT_ROWS #ifndef INVERT_ROWS
ROWPORT&= ~(1<<PIN_MCLR); ROWPORT &= ~(1 << PIN_MCLR);
ROWPORT|= (1<<PIN_MCLR); ROWPORT |= (1 << PIN_MCLR);
ROWPORT|= (1<<PIN_DATA); ROWPORT |= (1 << PIN_DATA);
ROWPORT|= (1<<PIN_CLK); ROWPORT |= (1 << PIN_CLK);
ROWPORT&= ~(1<<PIN_CLK); ROWPORT &= ~(1 << PIN_CLK);
ROWPORT&= ~(1<<PIN_DATA); ROWPORT &= ~(1 << PIN_DATA);
#else #else
ROWPORT&= ~(1<<PIN_DATA); ROWPORT&= ~(1<<PIN_DATA);
ROWPORT|= (1<<PIN_CLK); ROWPORT|= (1<<PIN_CLK);
@ -72,43 +70,33 @@ inline void nextrow(uint8_t row){
ROWPORT|= (1<<PIN_DATA); ROWPORT|= (1<<PIN_DATA);
#endif #endif
}else{ } else {
//In jeder anderen Zeile einfach nur einen weiter schieben // remaining rows: just shift forward
ROWPORT|= (1<<PIN_CLK); ROWPORT |= (1 << PIN_CLK);
ROWPORT&= ~(1<<PIN_CLK); ROWPORT &= ~(1 << PIN_CLK);
} }
//noch eine Warteschleife, damit die Zeilentreiber bereit sind // another delay loop, to ensure that the drivers are ready
for(i=0;i<20;i++){ for (i = 0; i < 20; i++) {
asm volatile("nop"); asm volatile("nop");
} }
} }
// show a row
static void rowshow(unsigned char row, unsigned char plane) {
// depending on the currently drawn plane, display the row for a specific
// amount of time
static unsigned char const ocr_table[] = {3, 4, 22};
OCR0 = ocr_table[plane];
// output data of the current row to the column drivers
//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; uint8_t tmp, tmp1;
//die Daten für die aktuelle Zeile auf die Spaltentreiber ausgeben
#ifndef INTERLACED_ROWS #ifndef INTERLACED_ROWS
tmp = pixmap[plane][row][0]; tmp = pixmap[plane][row][0];
tmp1 = pixmap[plane][row][1]; tmp1 = pixmap[plane][row][1];
#else #else
row = (row>>1) + ((row & 0x01)?8:0 ); row = (row>>1) + ((row & 0x01)?8:0 );
tmp = pixmap[plane][row][0]; tmp = pixmap[plane][row][0];
tmp1 = pixmap[plane][row][1]; tmp1 = pixmap[plane][row][1];
#endif #endif
#ifdef REVERSE_COLS #ifdef REVERSE_COLS
@ -124,44 +112,43 @@ inline void rowshow(unsigned char row, unsigned char plane){
#else #else
#ifdef INTERLACED_COLS #ifdef INTERLACED_COLS
static uint8_t interlace_table[16] = { static uint8_t interlace_table[16] = {
0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 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); COLPORT1 = interlace_table[tmp&0x0f] | (interlace_table[tmp1&0x0f]<<1);
tmp>>=4; tmp1>>=4; tmp>>=4; tmp1>>=4;
COLPORT2 = interlace_table[tmp] | (interlace_table[tmp1]<<1); COLPORT2 = interlace_table[tmp] | (interlace_table[tmp1]<<1);
#else #else
COLPORT1 = tmp; COLPORT1 = tmp;
COLPORT2 = tmp1; COLPORT2 = tmp1;
#endif #endif
#endif #endif
} }
// depending on the plane this interrupt triggers at 50 kHz, 31.25 kHz or
//Dieser Interrupt wird je nach Ebene mit 50kHz 31,25kHz oder 12,5kHz ausgeführt // 12.5 kHz
SIGNAL(SIG_OUTPUT_COMPARE0) SIGNAL(SIG_OUTPUT_COMPARE0) {
{
static unsigned char plane = 0; static unsigned char plane = 0;
static unsigned char row = 0; static unsigned char row = 0;
//Watchdog zurücksetzen // reset watchdog
wdt_reset(); wdt_reset();
//Zeile und Ebene inkrementieren // increment both row and plane
if(++plane==NUMPLANE){ if (++plane == NUMPLANE) {
plane=0; plane = 0;
if(++row == NUM_ROWS){ if (++row == NUM_ROWS) {
row = 0; row = 0;
} }
nextrow(row); nextrow(row);
} }
//Die aktuelle Zeile in der aktuellen Ebene ausgeben // output current row according to current plane
rowshow(row, plane); rowshow(row, plane);
} }
void timer0_off() {
void timer0_off(){
cli(); cli();
COLPORT1 = 0; COLPORT1 = 0;
@ -169,60 +156,59 @@ void timer0_off(){
ROWPORT = 0; ROWPORT = 0;
#ifdef __AVR_ATmega644P__ #ifdef __AVR_ATmega644P__
TCCR0A = 0x00; TCCR0A = 0x00;
TCCR0B = 0x00; TCCR0B = 0x00;
#else #else
TCCR0 = 0x00; TCCR0 = 0x00;
#endif #endif
sei(); sei();
} }
// initialize timer which triggers the interrupt
static 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
*/
// 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
*/
#ifdef __AVR_ATmega644P__ #ifdef __AVR_ATmega644P__
TCCR0A = 0x02; // CTC Mode TCCR0A = 0x02; // CTC Mode
TCCR0B = 0x04; // clk/256 TCCR0B = 0x04; // clk/256
TCNT0 = 0; // reset timer TCNT0 = 0; // reset timer
OCR0 = 20; // Compare with this value OCR0 = 20; // compare with this value
TIMSK0 = 0x02; // Compare match Interrupt on TIMSK0 = 0x02; // compare match Interrupt on
#else #else
TCCR0 = 0x0C; // CTC Mode, clk/256 TCCR0 = 0x0C; // CTC Mode, clk/256
TCNT0 = 0; // reset timer TCNT0 = 0; // reset timer
OCR0 = 20; // Compare with this value OCR0 = 20; // compare with this value
TIMSK = 0x02; // Compare match Interrupt on TIMSK = 0x02; // compare match Interrupt on
#endif #endif
} }
void borg_hw_init(){ void borg_hw_init() {
//Spalten Ports auf Ausgang // switch column ports to output mode
COLDDR1 = 0xFF; COLDDR1 = 0xFF;
COLDDR2 = 0xFF; COLDDR2 = 0xFF;
//Pins am Zeilenport auf Ausgang // switch pins of the row port to output mode
ROWDDR = (1<<PIN_MCLR) | (1<<PIN_CLK) | (1<< PIN_DATA); ROWDDR = (1 << PIN_MCLR) | (1 << PIN_CLK) | (1 << PIN_DATA);
//Alle Spalten erstmal aus // switch off all columns for now
COLPORT1 = 0; COLPORT1 = 0;
COLPORT2 = 0; COLPORT2 = 0;
//Schieberegister für Zeilen zurücksetzen // reset shift registers for the rows
ROWPORT = 0; ROWPORT = 0;
timer0_on(); timer0_on();
//Watchdog Timer aktivieren // activate watchdog timer
wdt_reset(); wdt_reset();
wdt_enable(0x00); // 17ms Watchdog wdt_enable(0x00); // 17ms watchdog
} }

View File

@ -1,4 +1,3 @@
#include "../config.h" #include "../config.h"
#include "../makros.h" #include "../makros.h"
@ -8,119 +7,123 @@
#include "borg_hw.h" #include "borg_hw.h"
/* /*
// Diese #defines werden nun durch menuconfig gesetzt // those macros get defined via menuconfig, now
#define ROWPORT PORTB #define ROWPORT PORTB
#define ROWDDR DDRB #define ROWDDR DDRB
#define COLPORT PORTD #define COLPORT PORTD
#define COLDDR DDRD #define COLDDR DDRD
#define PIN_DATA PC4 #define PIN_DATA PC4
#define PIN_CLK PC6 //active low #define PIN_CLK PC6 //active low
#define PIN_LINE_EN PC5 //active low #define PIN_LINE_EN PC5 //active low
*/ */
#define COLDDR DDR(COLPORT)
#define ROWDDR DDR(ROWPORT)
#define COLDDR DDR(COLPORT)
#define ROWDDR DDR(ROWPORT)
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
inline void rowshow(unsigned char row, unsigned char plane){ inline void rowshow(unsigned char row, unsigned char plane) {
COLPORT |= (1<<PIN_LINE_EN);//blank display COLPORT |= (1 << PIN_LINE_EN); //blank display
ROWPORT = (ROWPORT & 0xF8) | row; ROWPORT = (ROWPORT & 0xF8) | row;
unsigned char b, d, x; unsigned char b, d, x;
for(b=0;b<LINEBYTES;b++){ for (b = 0; b < LINEBYTES; b++) {
d = pixmap[plane][row][b]; d = pixmap[plane][row][b];
for(x=0;x<8;x++){ for (x = 0; x < 8; x++) {
if(d & 0x01){ if (d & 0x01) {
COLPORT |= (1<<PIN_DATA); COLPORT |= (1 << PIN_DATA);
}else{ } else {
COLPORT &= ~(1<<PIN_DATA); COLPORT &= ~(1 << PIN_DATA);
} }
d>>=1; d >>= 1;
COLPORT &= ~(1<<PIN_CLK); COLPORT &= ~(1 << PIN_CLK);
COLPORT |= (1<<PIN_CLK); COLPORT |= (1 << PIN_CLK);
} }
} }
COLPORT &= ~(1<<PIN_LINE_EN);//unblank display COLPORT &= ~(1 << PIN_LINE_EN); // unblank display
} }
SIGNAL(SIG_OUTPUT_COMPARE0)
{ SIGNAL(SIG_OUTPUT_COMPARE0) {
static unsigned char plane = 0; static unsigned char plane = 0;
static unsigned char row = 0; static unsigned char row = 0;
if (row == 0){ if (row == 0) {
switch (plane){ switch (plane) {
case 0: case 0:
OCR0 = 7; OCR0 = 7;
break; break;
case 1: case 1:
OCR0 = 20; OCR0 = 20;
break; break;
case 2: case 2:
OCR0 = 40; OCR0 = 40;
} }
} }
rowshow(row, plane); rowshow(row, plane);
if(++row == NUM_ROWS){ if (++row == NUM_ROWS) {
row = 0; row = 0;
if(++plane==NUMPLANE) plane=0; if (++plane == NUMPLANE)
plane = 0;
} }
wdt_reset(); 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
void timer0_on(){ */
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00 TCCR0 = 0x08 | 0x04; // CTC Mode, clk/256
CS02 CS01 CS00 TCNT0 = 0; // reset timer
0 0 0 stop OCR0 = 0x30; // compare with this value
0 0 1 clk TIMSK = 0x02; // compare match Interrupt on
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(){
void timer0_off() {
cli(); cli();
COLPORT |= (1<<PIN_LINE_EN);//blank display COLPORT |= (1 << PIN_LINE_EN); //blank display
TCCR0 = 0x00; TCCR0 = 0x00;
sei(); sei();
} }
void watchdog_enable()
{ void watchdog_enable() {
wdt_reset(); wdt_reset();
wdt_enable(0x00); // 17ms wdt_enable(0x00); // 17ms
} }
void borg_hw_init(){
COLPORT |= (1<<PIN_CLK) | (1<<PIN_LINE_EN); void borg_hw_init() {
COLDDR |= (1<<PIN_CLK) | (1<<PIN_LINE_EN) | (1<<PIN_DATA); COLPORT |= (1 << PIN_CLK) | (1 << PIN_LINE_EN);
COLDDR |= (1 << PIN_CLK) | (1 << PIN_LINE_EN) | (1 << PIN_DATA);
ROWDDR |= 0x07; ROWDDR |= 0x07;
watchdog_enable(); watchdog_enable();
timer0_on(); timer0_on();
} }

View File

@ -1,4 +1,3 @@
#include "../config.h" #include "../config.h"
#include "../makros.h" #include "../makros.h"
@ -8,7 +7,6 @@
#include "borg_hw.h" #include "borg_hw.h"
#define ROWPORT PORTC #define ROWPORT PORTC
#define ROWDDR DDRC #define ROWDDR DDRC
@ -26,125 +24,113 @@
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
inline void rowshow(unsigned char row, unsigned char plane) {
inline void rowshow(unsigned char row, unsigned char plane){ unsigned char p, n, m, outb, clkmsk;
unsigned char p, n,m, outb, clkmsk;
clkmsk = 0x80>>row; clkmsk = 0x80 >> row;
// if (row==4)
{
MYPORT &= ~(1 << PIN_ENABLE) ;
//MYPORT |= (1 << PIN_ENABLE) ; //hide
// MYPORT |= (1 << PIN_ENABLE) ; //hide
for (n=7;n<8;n--)
{
outb = pixmap[plane][row][n];
p=0x80;
for (m=0;m<8;m++)
{
if (outb & p)
// MYPORT |= (1 << PIN_DATA);
MYPORT &= ~(1 << PIN_DATA) ;
else
// MYPORT &= ~(1 << PIN_DATA) ; //off
MYPORT |= (1 << PIN_DATA);
MYPORT2 &= ~clkmsk ;
MYPORT2 |= clkmsk ;
p>>=1; // if (row==4)
{
MYPORT &= ~(1 << PIN_ENABLE);
// MYPORT |= (1 << PIN_ENABLE); //hide
// MYPORT |= (1 << PIN_ENABLE); //hide
for (n = 7; n < 8; n--) {
outb = pixmap[plane][row][n];
p = 0x80;
for (m = 0; m < 8; m++) {
if (outb & p)
// MYPORT |= (1 << PIN_DATA);
MYPORT &= ~(1 << PIN_DATA);
else
// MYPORT &= ~(1 << PIN_DATA); //off
MYPORT |= (1 << PIN_DATA);
} MYPORT2 &= ~clkmsk;
} MYPORT2 |= clkmsk;
}
MYPORT |= (1 << PIN_ENABLE) ; //
//MYPORT &= ~(1 << PIN_ENABLE) ;
// for(n=0;n<250;n++) asm ("nop");
p >>= 1;
}
}
}
MYPORT |= (1 << PIN_ENABLE);
//MYPORT &= ~(1 << PIN_ENABLE) ;
// for(n=0;n<250;n++) asm ("nop");
} }
SIGNAL(SIG_OUTPUT_COMPARE0) SIGNAL( SIG_OUTPUT_COMPARE0) {
{ static unsigned char plane = 0;
static unsigned char plane = 0; unsigned char row = 0;
unsigned char row = 0;
switch (plane){ switch (plane) {
case 0: case 0:
OCR0 = 60; OCR0 = 60;
break; break;
case 1: case 1:
OCR0 = 120; OCR0 = 120;
break; break;
case 2: case 2:
OCR0 = 160; OCR0 = 160;
break; break;
// case 3: // case 3:
// OCR0 = 24; // OCR0 = 24;
// break; // break;
// case 4: // case 4:
// OCR0 = 48; // OCR0 = 48;
// break; // break;
} }
for(row=0;row<NUM_ROWS;row++){ for (row = 0; row < NUM_ROWS; row++) {
rowshow(row, plane); rowshow(row, plane);
} }
if(++plane==NUMPLANE) plane=0; if (++plane == NUMPLANE)
wdt_reset(); plane = 0;
wdt_reset();
} }
void timer0_on() {
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
void timer0_on(){ CS02 CS01 CS00
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00 0 0 0 stop
CS02 CS01 CS00 0 0 1 clk
0 0 0 stop 0 1 0 clk/8
0 0 1 clk 0 1 1 clk/64
0 1 0 clk/8 1 0 0 clk/256
0 1 1 clk/64 1 0 1 clk/1024
1 0 0 clk/256 */
1 0 1 clk/1024 TCCR0 = 0x08 | 0x04; // CTC Mode, clk/256 MH: slower 5 instead of 4
TCNT0 = 0; // reset timer
*/ OCR0 = 0x30; // compare with this value 0x30
TCCR0 = 0x08 |0x04; // CTC Mode, clk/256 MH: slower 5 statt 4 TIMSK = 0x02; // compare match Interrupt on
TCNT0 = 0; // reset timer
OCR0 = 0x30; // Compare with this value 0x30
TIMSK = 0x02; // Compare match Interrupt on
} }
void timer0_off(){ void timer0_off() {
cli(); cli();
MYPORT &= ~(1 << PIN_ENABLE) ; MYPORT &= ~(1 << PIN_ENABLE);
//MYPORT |= (1 << PIN_ENABLE) ; //hide // MYPORT |= (1 << PIN_ENABLE); // hide
//COLPORT |= (1<<PIN_LINE_EN);//blank display // COLPORT |= (1<<PIN_LINE_EN); // blank display
// PORTD |= 0x01;//blank display // PORTD |= 0x01; // blank display
TCCR0 = 0x00; TCCR0 = 0x00;
sei(); sei();
} }
void watchdog_enable() void watchdog_enable() {
{ wdt_reset();
wdt_reset(); wdt_enable(0x00); // 17ms
wdt_enable(0x00); // 17ms
} }
void borg_hw_init(){ void borg_hw_init() {
//COLPORT |= (1<<PIN_CLK) | (1<<PIN_LINE_EN); //COLPORT |= (1<<PIN_CLK) | (1<<PIN_LINE_EN);
//COLDDR |= (1<<PIN_CLK) | (1<<PIN_LINE_EN) | (1<<PIN_DATA); //COLDDR |= (1<<PIN_CLK) | (1<<PIN_LINE_EN) | (1<<PIN_DATA);
//ROWDDR |= 0x07; //ROWDDR |= 0x07;
DDRA = 0xFF;
DDRC = 0xFF; DDRA = 0xFF;
DDRC = 0xFF;
watchdog_enable();
timer0_on(); watchdog_enable();
timer0_on();
} }

View File

@ -1,4 +1,3 @@
#include "../config.h" #include "../config.h"
#include "../makros.h" #include "../makros.h"
@ -8,24 +7,26 @@
#include "borg_hw.h" #include "borg_hw.h"
/* /*
// Diese #defines werden nun durch menuconfig gesetzt // those macros get defined via menuconfig, now
// 16 Spalten insgesamt direkt gesteuert, dafür 2 Ports // 16 columns total directly controlled, therefore 2 ports
#define COLPORT1 PORTC #define COLPORT1 PORTC
#define COLDDR1 DDRC #define COLDDR1 DDRC
#define COLPORT2 PORTA #define COLPORT2 PORTA
#define COLDDR2 DDRA #define COLDDR2 DDRA
// Der andere Port übernimmt die Steuerung der Schieberegister // the other port controls the shift registers
#define ROWPORT PORTD #define ROWPORT PORTD
#define ROWDDR DDRD #define ROWDDR DDRD
// Clock und reset gehen gemeinsam an beide Schieberegister
// der reset pin ist negiert // both clock and reset are connected to each shift register
#define PIN_MCLR PD4 // reset pin is negated
#define PIN_CLK PD6 #define PIN_MCLR PD4
//das dier sind die individuellen Dateneingänge für die Schieberegister #define PIN_CLK PD6
#define PIN_DATA PD7
// these are the individual data input pins for the shift registers
#define PIN_DATA PD7
*/ */
#define COLDDR1 DDR(COLPORT1) #define COLDDR1 DDR(COLPORT1)
@ -39,23 +40,22 @@
#endif #endif
//Der Puffer, in dem das aktuelle Bild gespeichert wird // buffer which holds the currently shown frame
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
//Dieser Interrupt wird je nach Ebene mit 50kHz 31,25kHz oder 12,5kHz ausgeführt // depending on the plane this interrupt gets triggered at 50 kHz, 31.25 kHz or
SIGNAL(SIG_OUTPUT_COMPARE0) // 12.5 kHz
{ SIGNAL( SIG_OUTPUT_COMPARE0) {
//Watchdog zurücksetzen // reset watchdog
wdt_reset(); wdt_reset();
COLPORT1 = (pixmap[0][0][0] & 0x0f) | (pixmap[0][1][0] << 4); COLPORT1 = (pixmap[0][0][0] & 0x0f) | (pixmap[0][1][0] << 4);
COLPORT2 = (pixmap[0][2][0] & 0x0f) | (pixmap[0][3][0] << 4); COLPORT2 = (pixmap[0][2][0] & 0x0f) | (pixmap[0][3][0] << 4);
} }
void timer0_off(){ void timer0_off() {
cli(); cli();
COLPORT1 = 0; COLPORT1 = 0;
@ -63,69 +63,67 @@ void timer0_off(){
ROWPORT = 0; ROWPORT = 0;
#ifdef __AVR_ATmega644P__ #ifdef __AVR_ATmega644P__
TCCR0A = 0x00; TCCR0A = 0x00;
TCCR0B = 0x00; TCCR0B = 0x00;
#else #else
TCCR0 = 0x00; TCCR0 = 0x00;
#endif #endif
sei(); sei();
} }
// Den Timer, der denn Interrupt auslöst, initialisieren // initialize timer which triggers the interrupt
void timer0_on(){ void timer0_on() {
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00 /* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
CS02 CS01 CS00 CS02 CS01 CS00
0 0 0 stop 0 0 0 stop
0 0 1 clk 0 0 1 clk
0 1 0 clk/8 0 1 0 clk/8
0 1 1 clk/64 0 1 1 clk/64
1 0 0 clk/256 1 0 0 clk/256
1 0 1 clk/1024 1 0 1 clk/1024
*/
*/
#ifdef __AVR_ATmega644P__ #ifdef __AVR_ATmega644P__
TCCR0A = 0x02; // CTC Mode TCCR0A = 0x02; // CTC Mode
TCCR0B = 0x04; // clk/256 TCCR0B = 0x04; // clk/256
TCNT0 = 0; // reset timer TCNT0 = 0; // reset timer
OCR0 = 20; // Compare with this value OCR0 = 20; // compare with this value
TIMSK0 = 0x02; // Compare match Interrupt on TIMSK0 = 0x02; // compare match Interrupt on
#else #else
TCCR0 = 0x0C; // CTC Mode, clk/256 TCCR0 = 0x0C; // CTC Mode, clk/256
TCNT0 = 0; // reset timer TCNT0 = 0; // reset timer
OCR0 = 20; // Compare with this value OCR0 = 20; // compare with this value
TIMSK = 0x02; // Compare match Interrupt on TIMSK = 0x02; // compare match Interrupt on
#endif #endif
} }
void borg_hw_init(){
//Spalten Ports auf Ausgang void borg_hw_init() {
// switch column ports to output mode
COLDDR1 = 0xFF; COLDDR1 = 0xFF;
COLDDR2 = 0xFF; COLDDR2 = 0xFF;
//Pins am Zeilenport auf Ausgang // switch pins of the row port to output mode
ROWDDR = (1<<PIN_MCLR) | (1<<PIN_CLK) | (1<< PIN_DATA); ROWDDR = (1 << PIN_MCLR) | (1 << PIN_CLK) | (1 << PIN_DATA);
//Alle Spalten erstmal aus // switch off all columns for now
COLPORT1 = 0; COLPORT1 = 0;
COLPORT2 = 0; COLPORT2 = 0;
//Schieberegister für Zeilen zurücksetzen // reset shift registers for the rows
ROWPORT = 0; ROWPORT = 0;
//Alle Zeilen ausgänge an bei gigaborg // switch on all row output ports of the gigaborg
ROWPORT |= (1<<PIN_DATA) | (1<<PIN_MCLR); ROWPORT |= (1 << PIN_DATA) | (1 << PIN_MCLR);
uint8_t x; uint8_t x;
for(x=0;x<16;x++){ for (x = 0; x < 16; x++) {
ROWPORT|= (1<<PIN_CLK); ROWPORT |= (1 << PIN_CLK);
ROWPORT&= ~(1<<PIN_CLK); ROWPORT &= ~(1 << PIN_CLK);
} }
timer0_on(); timer0_on();
//Watchdog Timer aktivieren // activate watchdog timer
wdt_reset(); wdt_reset();
wdt_enable(0x00); // 17ms Watchdog wdt_enable(0x00); // 17ms watchdog
} }

View File

@ -1,15 +1,15 @@
#include"../autoconf.h" #include"../autoconf.h"
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <avr/io.h> #include <avr/io.h>
#include <avr/wdt.h> #include <avr/wdt.h>
#include "borg_hw.h" #include "borg_hw.h"
/* Steckerbelegung Flachbandkabel am Panel
* (die Nummerierung ist in wirklichkeit umgekehrt) /* pinout of the ribbon cable connected to the panel
* (the numbering is actually upside down)
* *
* 1-3 GND * 1-3 GND
* 4 +5V für Logic * 4 +5V for logic
* 5-8 +12V * 5-8 +12V
* 9-10 GND * 9-10 GND
* 11 CP3 * 11 CP3
@ -21,7 +21,7 @@
* 17-18 GND * 17-18 GND
* 19-26 D0-D7 * 19-26 D0-D7
* *
* Und nochmal richtigrum: * and now the right way round:
* 1 D7 * 1 D7
* 2 D6 * 2 D6
* 3 D5 * 3 D5
@ -49,22 +49,20 @@
* 25 GND * 25 GND
* 26 GND * 26 GND
* *
* Es werden 4 40374 Latches benutzt. Nr. 1,2 und 4 treiben vom Datenbus * Four 40374 latches are used. No. 1, 2 and 4 drive from the data bus to the
* in Richtung Panel, Nr. 3 treibt von den Tastenausgängen auf den Datenbus. * panel, no. 3 drives from the button outputs to the data bus. The EOs of
* Die EOs von 1,2 und 4 liegen fest auf GND. * 1, 2 and 4 are hardwired to GND.
* *
* Die LEDs sind in einer 12*16 Matrix angeordnet * The LEDs are aligned to a 12*16 matrix. The values for the LED columns are
* Die Werte für die LED spalten Werden mit CP1 und CP2 in die * passed to the latches via CP1 und CP2 (16 columns total). The index of the
* Latches übernommen (insgesammt 16 Spalten) * row is passed during the deletion of "/show".
* Die Nummer der Zeile wird beim löschen von /show übernommen.
* *
* Die Tasten sind in einer 8*8 Matrix angeordnet. * The buttons are aligned to an 8*8 matrix. The rows get separately set to
* Über Latch 4 werden die Zeilen einzeln auf high gesetzt, über * "high" via latch 4. The columns can then be read via latch 3.
* Latch 3 können dann die Spalten gelesen werden.
*
*/ */
//Datenport für das Panel
// data port for the panel
#define COLPORT PORTC #define COLPORT PORTC
#define COLDDR DDRC #define COLDDR DDRC
#define COLPIN PINC #define COLPIN PINC
@ -72,7 +70,7 @@
#define CTRLPORT PORTD #define CTRLPORT PORTD
#define CTRLDDR DDRD #define CTRLDDR DDRD
// PINs on CTRLPORT // pins on CTRLPORT
#define PIN_EO3 PD7 #define PIN_EO3 PD7
#define PIN_CP4 PD2 #define PIN_CP4 PD2
#define PIN_SHOW PD3 #define PIN_SHOW PD3
@ -80,84 +78,88 @@
#define PIN_CP2 PD5 #define PIN_CP2 PD5
#define PIN_CP3 PD6 #define PIN_CP3 PD6
//Der Puffer, in dem das aktuelle Bild gespeichert wird
// buffer which holds the currently shown frame
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
volatile uint8_t keys[8]; volatile uint8_t keys[8];
inline void busywait() { inline void busywait() {
//unsigned char i; //unsigned char i;
//for(i=0;i<20;i++){ //for(i=0; i < 20; i++){
// asm volatile("nop"); // asm volatile("nop");
//} //}
} }
//Eine Zeile anzeigen // display a row
inline void rowshow(unsigned char row, unsigned char plane){ inline void rowshow(unsigned char row, unsigned char plane){
CTRLPORT |= (1<<PIN_SHOW);//blank CTRLPORT |= (1 << PIN_SHOW); //blank
COLPORT = pixmap[plane][row][0]; COLPORT = pixmap[plane][row][0];
busywait(); busywait();
CTRLPORT |= (1<<PIN_CP1); CTRLPORT |= (1 << PIN_CP1);
busywait(); busywait();
CTRLPORT &= ~(1<<PIN_CP1); CTRLPORT &= ~(1 << PIN_CP1);
busywait(); busywait();
COLPORT = pixmap[plane][row][1]; COLPORT = pixmap[plane][row][1];
busywait(); busywait();
CTRLPORT |= (1<<PIN_CP2); CTRLPORT |= (1 << PIN_CP2);
busywait(); busywait();
CTRLPORT &= ~(1<<PIN_CP2); CTRLPORT &= ~(1 << PIN_CP2);
busywait(); busywait();
COLPORT = row; COLPORT = row;
busywait(); busywait();
CTRLPORT &= ~(1<<PIN_SHOW); CTRLPORT &= ~(1 << PIN_SHOW);
} }
inline void checkkeys(uint8_t row){ inline void checkkeys(uint8_t row){
static uint8_t mask; static uint8_t mask;
if(row == 0){ if (row == 0) {
mask = 1; mask = 1;
}else{ } else {
//read keyboard cols into latch //read keyboard cols into latch
COLDDR = 0; COLDDR = 0;
CTRLPORT &= ~(1<<PIN_EO3); CTRLPORT &= ~(1 << PIN_EO3);
CTRLPORT |= (1<<PIN_CP3); CTRLPORT |= (1 << PIN_CP3);
busywait(); busywait();
CTRLPORT &= ~(1<<PIN_CP3); CTRLPORT &= ~(1 << PIN_CP3);
busywait(); busywait();
keys[row-1] = COLPIN; keys[row - 1] = COLPIN;
CTRLPORT |= (1<<PIN_EO3); CTRLPORT |= (1 << PIN_EO3);
busywait(); busywait();
COLDDR = 0xFF; COLDDR = 0xFF;
} }
COLPORT = mask; COLPORT = mask;
mask <<= 1; mask <<= 1;
busywait(); busywait();
CTRLPORT |= (1<<PIN_CP4); CTRLPORT |= (1 << PIN_CP4);
busywait(); busywait();
CTRLPORT &= ~(1<<PIN_CP4); CTRLPORT &= ~(1 << PIN_CP4);
} }
//Dieser Interrupt wird je nach Ebene mit 50kHz 31,25kHz oder 12,5kHz ausgeführt
// depending on the plane this interrupt gets triggered at 50 kHz, 31.25 kHz or
// 12.5 kHz
SIGNAL(SIG_OUTPUT_COMPARE0) SIGNAL(SIG_OUTPUT_COMPARE0)
{ {
static unsigned char plane = 0; static unsigned char plane = 0;
static unsigned char row = 0; static unsigned char row = 0;
//Watchdog zurücksetzen // reset watchdog
wdt_reset(); wdt_reset();
//Die aktuelle Zeile in der aktuellen Ebene ausgeben // output current row according to current plane
rowshow(row, plane); rowshow(row, plane);
if( (plane == 2) && (row<9) ) checkkeys(row); if( (plane == 2) && (row<9) ) checkkeys(row);
//Zeile und Ebene inkrementieren // increment both row and plane
if(++row == NUM_ROWS){ if(++row == NUM_ROWS){
row = 0; row = 0;
if(++plane==NUMPLANE) plane=0; if(++plane==NUMPLANE) plane=0;
@ -184,37 +186,38 @@ void timer0_off(){
} }
// Den Timer, der denn Interrupt auslöst, initialisieren // initialize timer which triggers the interrupt
void timer0_on(){ void timer0_on(){
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00 /* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
CS02 CS01 CS00 CS02 CS01 CS00
0 0 0 stop 0 0 0 stop
0 0 1 clk 0 0 1 clk
0 1 0 clk/8 0 1 0 clk/8
0 1 1 clk/64 0 1 1 clk/64
1 0 0 clk/256 1 0 0 clk/256
1 0 1 clk/1024 1 0 1 clk/1024
*/
*/ TCCR0 = 0x0C; // CTC Mode, clk/64
TCCR0 = 0x0C; // CTC Mode, clk/64 TCNT0 = 0; // reset timer
TCNT0 = 0; // reset timer OCR0 = 20; // compare with this value
OCR0 = 20; // Compare with this value TIMSK = 0x02; // compare match Interrupt on
TIMSK = 0x02; // Compare match Interrupt on
} }
void borg_hw_init(){ void borg_hw_init(){
//Pins am Zeilenport auf Ausgang //Pins am Zeilenport auf Ausgang
CTRLPORT |= (1<<PIN_EO3)|(1<<PIN_SHOW); CTRLPORT |= (1 << PIN_EO3) | (1 << PIN_SHOW);
CTRLDDR |= (1<<PIN_EO3) | (1<<PIN_CP4) | (1<<PIN_SHOW) | (1<<PIN_CP1) | (1<<PIN_CP2) | (1<<PIN_CP3); CTRLDDR |= (1 << PIN_EO3) | (1 << PIN_CP4) | (1 << PIN_SHOW)
| (1 << PIN_CP1) | (1 << PIN_CP2) | (1 << PIN_CP3);
//Alle Spalten erstmal aus
//Spalten Ports auf Ausgang // switch off all columns for now
COLDDR = 0xFF; // switch column ports to output mode
COLDDR = 0xFF;
COLPORT = 0x00; COLPORT = 0x00;
timer0_on(); timer0_on();
//Watchdog Timer aktivieren // activate watchdog timer
wdt_reset(); wdt_reset();
wdt_enable(0x00); // 17ms Watchdog wdt_enable(0x00); // 17ms watchdog
} }

View File

@ -1,4 +1,3 @@
#include "../config.h" #include "../config.h"
#include "../makros.h" #include "../makros.h"
@ -8,30 +7,31 @@
#include "borg_hw.h" #include "borg_hw.h"
/* /*
// Diese #defines werden nun durch menuconfig gesetzt // those macros get defined via menuconfig, now
// 16 Spalten insgesamt direkt gesteuert, dafür 2 Ports // 16 columns total directly controlled, therefore 2 ports
#define COLPORT1 PORTC #define COLPORT1 PORTC
#define COLDDR1 DDRC #define COLDDR1 DDRC
#define COLPORT2 PORTA #define COLPORT2 PORTA
#define COLDDR2 DDRA #define COLDDR2 DDRA
// Der andere Port übernimmt die Steuerung der Schieberegister // the other port controls the shift registers
#define ROWPORT PORTD #define ROWPORT PORTD
#define ROWDDR DDRD #define ROWDDR DDRD
// Clock und reset gehen gemeinsam an beide Schieberegister
// der reset pin ist negiert // both clock and reset are connected to each shift register
#define PIN_MCLR PD4 // reset pin is negated
#define PIN_CLK PD6 #define PIN_MCLR PD4
//das dier sind die individuellen Dateneingänge für die Schieberegister #define PIN_CLK PD6
#define PIN_DATA PD7
*/ // these are the individual data input pins for the shift registers
#define PIN_DATA PD7
*/
//#define COLDDR1 DDR(COLPORT1) //#define COLDDR1 DDR(COLPORT1)
//#define COLDDR2 DDR(COLPORT2) //#define COLDDR2 DDR(COLPORT2)
//#define ROWDDR DDR(ROWPORT) //#define ROWDDR DDR(ROWPORT)
//#define DATAPORT PORTC //#define DATAPORT PORTC
#define DATADDR DDR(DATAPORT) #define DATADDR DDR(DATAPORT)
@ -50,64 +50,63 @@
//#define BIT_RW 6 //#define BIT_RW 6
//Der Puffer, in dem das aktuelle Bild gespeichert wird // buffer which holds the currently shown frame
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
inline void pd1165_write(uint8_t addr, uint8_t data) {
inline void pd1165_write(uint8_t addr, uint8_t data){
ADDRPORT = (ADDRPORT & 0xf0) | addr; ADDRPORT = (ADDRPORT & 0xf0) | addr;
DATAPORT = data; DATAPORT = data;
/* /*
switch (display){ switch (display) {
case 0: case 0:
CTRLPORT &= ~((1<<BIT_CS0)|(1<<BIT_RW)); CTRLPORT &= ~((1 << BIT_CS0) | (1 << BIT_RW));
CTRLPORT |= ((1<<BIT_CS0)); CTRLPORT |= ((1 << BIT_CS0));
break; break;
case 1: case 1:
CTRLPORT &= ~((1<<BIT_CS1)|(1<<BIT_RW)); CTRLPORT &= ~((1 << BIT_CS1) | (1 << BIT_RW));
CTRLPORT |= ((1<<BIT_CS1)); CTRLPORT |= ((1 << BIT_CS1));
break; break;
case 2: case 2:
CTRLPORT &= ~((1<<BIT_CS2)|(1<<BIT_RW)); CTRLPORT &= ~((1 << BIT_CS2) | (1 << BIT_RW));
CTRLPORT |= ((1<<BIT_CS2)); CTRLPORT |= ((1 << BIT_CS2));
break; break;
case 3: case 3:
CTRLPORT &= ~((1<<BIT_CS3)|(1<<BIT_RW)); CTRLPORT &= ~((1 << BIT_CS3) | (1 << BIT_RW));
CTRLPORT |= ((1<<BIT_CS3)); CTRLPORT |= ((1 << BIT_CS3));
break; break;
} }
*/ */
} }
/* /*
//Eine Zeile anzeigen // display a row
inline void rowshow(unsigned char row, unsigned char plane){ inline void rowshow(unsigned char row, unsigned char plane) {
int addr = row; int addr = row;
//Je nachdem, welche der Ebenen wir Zeichnen, die Zeile verschieden lange Anzeigen // depending on the currently drawn plane, display the row for a specific
switch (plane){ // amount of time
case 0: switch (plane) {
OCR0 = 3; case 0:
break; OCR0 = 3;
case 1: break;
OCR0 = 4; case 1:
break; OCR0 = 4;
case 2: break;
OCR0 = 22; case 2:
OCR0 = 22;
} }
uint8_t tmp, tmp1; uint8_t tmp, tmp1;
//die Daten für die aktuelle Zeile auf die Spaltentreiber ausgeben // output data of current row to the column drivers
#ifndef INTERLACED_ROWS #ifndef INTERLACED_ROWS
tmp = pixmap[plane][row][0]; tmp = pixmap[plane][row][0];
tmp1 = pixmap[plane][row][1]; tmp1 = pixmap[plane][row][1];
#else #else
row = (row>>1) + ((row & 0x01)?8:0 ); row = (row>>1) + ((row & 0x01)?8:0 );
tmp = pixmap[plane][row][0]; tmp = pixmap[plane][row][0];
tmp1 = pixmap[plane][row][1]; tmp1 = pixmap[plane][row][1];
#endif #endif
#ifdef REVERSE_COLS #ifdef REVERSE_COLS
@ -123,7 +122,8 @@ inline void rowshow(unsigned char row, unsigned char plane){
#else #else
#ifdef INTERLACED_COLS #ifdef INTERLACED_COLS
static uint8_t interlace_table[16] = { static uint8_t interlace_table[16] = {
0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 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); //COLPORT1 = interlace_table[tmp&0x0f] | (interlace_table[tmp1&0x0f]<<1);
tmp>>=4; tmp1>>=4; tmp>>=4; tmp1>>=4;
@ -133,147 +133,142 @@ inline void rowshow(unsigned char row, unsigned char plane){
//COLPORT2 = tmp1; //COLPORT2 = tmp1;
pd1165_write(row, tmp); pd1165_write(row, tmp);
#endif #endif
#endif #endif
} }
*/ */
//Dieser Interrupt wird je nach Ebene mit 50kHz 31,25kHz oder 12,5kHz ausgeführt
SIGNAL(SIG_OUTPUT_COMPARE0) // depending on the plane this interrupt gets triggered at 50 kHz, 31.25 kHz or
{ // 12.5 kHz
SIGNAL(SIG_OUTPUT_COMPARE0) {
static unsigned char plane = 0; static unsigned char plane = 0;
unsigned char row = 0; unsigned char row = 0;
//Watchdog zurücksetzen // reset watchdog
wdt_reset(); wdt_reset();
//Tasten für joystick einlesen // determine button status of the joystick
readButtons(); readButtons();
for(row=0; row < 8; row++){ for (row = 0; row < 8; row++) {
pd1165_write(row, pixmap[plane][row][0]); pd1165_write(row, pixmap[plane][row][0]);
CTRLPORT &= ~((1<<BIT_CS3)|(1<<BIT_RW)); CTRLPORT &= ~((1 << BIT_CS3) | (1 << BIT_RW));
CTRLPORT |= ((1<<BIT_CS3)); CTRLPORT |= ((1 << BIT_CS3));
pd1165_write(row, pixmap[plane][row][1]); pd1165_write(row, pixmap[plane][row][1]);
CTRLPORT &= ~((1<<BIT_CS2)|(1<<BIT_RW)); CTRLPORT &= ~((1 << BIT_CS2) | (1 << BIT_RW));
CTRLPORT |= ((1<<BIT_CS2)); CTRLPORT |= ((1 << BIT_CS2));
//pd1165_write(0, row, pixmap[plane][row][0]); //pd1165_write(0, row, pixmap[plane][row][0]);
//pd1165_write(1, row, pixmap[plane][row][1]); //pd1165_write(1, row, pixmap[plane][row][1]);
}
} for (row = 8; row < NUM_ROWS; row++) {
pd1165_write(row - 8, pixmap[plane][row][0]);
for(row=8; row < NUM_ROWS; row++){ CTRLPORT &= ~((1 << BIT_CS0) | (1 << BIT_RW));
pd1165_write(row-8, pixmap[plane][row][0]); CTRLPORT |= ((1 << BIT_CS0));
CTRLPORT &= ~((1<<BIT_CS0)|(1<<BIT_RW));
CTRLPORT |= ((1<<BIT_CS0));
pd1165_write(row-8, pixmap[plane][row][1]); pd1165_write(row - 8, pixmap[plane][row][1]);
CTRLPORT &= ~((1<<BIT_CS1)|(1<<BIT_RW)); CTRLPORT &= ~((1 << BIT_CS1) | (1 << BIT_RW));
CTRLPORT |= ((1<<BIT_CS1)); CTRLPORT |= ((1 << BIT_CS1));
} }
//Je nachdem, welche der Ebenen wir Zeichnen, die Zeile verschieden lange Anzeigen // depending on the currently drawn plane, display the row for a specific
switch (plane){ // amount of time
case 0: switch (plane) {
OCR0 = 3; case 0:
break; OCR0 = 3;
case 1: break;
OCR0 = 4; case 1:
break; OCR0 = 4;
case 2: break;
OCR0 = 22; case 2:
OCR0 = 22;
break;
} }
//increment both row and plane
//Zeile und Ebene inkrementieren if (++plane == NUMPLANE) {
if(++plane==NUMPLANE){ plane = 0;
plane=0;
} }
} }
void timer0_off(){ void timer0_off() {
cli(); cli();
TCCR0 = 0x00; TCCR0 = 0x00;
sei(); sei();
} }
// Den Timer, der denn Interrupt auslöst, initialisieren // initialize timer which triggers the interrupt
void timer0_on(){ void timer0_on() {
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00 /* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
CS02 CS01 CS00 CS02 CS01 CS00
0 0 0 stop 0 0 0 stop
0 0 1 clk 0 0 1 clk
0 1 0 clk/8 0 1 0 clk/8
0 1 1 clk/64 0 1 1 clk/64
1 0 0 clk/256 1 0 0 clk/256
1 0 1 clk/1024 1 0 1 clk/1024
*/ */
TCCR0 = 0x0D; // CTC Mode, clk/64 TCCR0 = 0x0D; // CTC Mode, clk/64
TCNT0 = 0; // reset timer TCNT0 = 0; // reset timer
OCR0 = 20; // Compare with this value OCR0 = 20; // compare with this value
TIMSK = 0x02; // Compare match Interrupt on TIMSK = 0x02; // compare match Interrupt on
} }
void timer2_on(){
/* TCCR2: FOC2 WGM20 COM21 COM20 WGM21 CS22 CS21 CS20
CS02 CS01 CS00
0 0 0 stop
0 0 1 clk
0 1 0 clk/8
0 1 1 clk/32
1 0 0 clk/64
1 0 1 clk/128
1 1 0 clk/256
1 1 1 clk/1024
Table 51. Compare Output Mode, non-PWM Mode
COM21 COM20 Description
0 0 Normal port operation, OC2 disconnected.
0 1 Toggle OC2 on compare match
1 0 Clear OC2 on compare match
1 1 Set OC2 on compare match
*/
TCCR2 = (1<<WGM21) | (1<<COM20) | 1 ; //CTC, OC2 toggle, clk/1
OCR2 = 92; //80kHz clock on OC2
void timer2_on() {
/* TCCR2: FOC2 WGM20 COM21 COM20 WGM21 CS22 CS21 CS20
CS02 CS01 CS00
0 0 0 stop
0 0 1 clk
0 1 0 clk/8
0 1 1 clk/32
1 0 0 clk/64
1 0 1 clk/128
1 1 0 clk/256
1 1 1 clk/1024
Table 51. Compare Output Mode, non-PWM Mode
COM21 COM20 Description
0 0 normal port operation, OC2 disconnected.
0 1 toggle OC2 on compare match
1 0 clear OC2 on compare match
1 1 set OC2 on compare match
*/
TCCR2 = (1 << WGM21) | (1 << COM20) | 1; //CTC, OC2 toggle, clk/1
OCR2 = 92; // 80kHz clock on OC2
} }
void borg_hw_init(){
void borg_hw_init() {
CTRLDDR = (1<<BIT_CS0)|(1<<BIT_CS1)|(1<<BIT_CS2)|(1<<BIT_CS3)|(1<<BIT_RW); CTRLDDR = (1<<BIT_CS0)|(1<<BIT_CS1)|(1<<BIT_CS2)|(1<<BIT_CS3)|(1<<BIT_RW);
CTRLPORT = (1<<BIT_CS0)|(1<<BIT_CS1)|(1<<BIT_CS2)|(1<<BIT_CS3)|(1<<BIT_RW); CTRLPORT = (1<<BIT_CS0)|(1<<BIT_CS1)|(1<<BIT_CS2)|(1<<BIT_CS3)|(1<<BIT_RW);
DATADDR = 0xff; DATADDR = 0xff;
ADDRDDR |= 0x0f; ADDRDDR |= 0x0f;
CTRLPORT = (1<<BIT_CS0)|(1<<BIT_CS1)|(1<<BIT_CS2)|(1<<BIT_CS3)|(1<<BIT_RW); CTRLPORT = (1<<BIT_CS0)|(1<<BIT_CS1)|(1<<BIT_CS2)|(1<<BIT_CS3)|(1<<BIT_RW);
pd1165_write(8, 0x10|7);
pd1165_write(8, 0x10 | 7);
CTRLPORT &= ~((1<<BIT_CS0)|(1<<BIT_CS1)|(1<<BIT_CS2)|(1<<BIT_CS3)|(1<<BIT_RW)); CTRLPORT &= ~((1<<BIT_CS0)|(1<<BIT_CS1)|(1<<BIT_CS2)|(1<<BIT_CS3)|(1<<BIT_RW));
CTRLPORT |= ((1<<BIT_CS0)|(1<<BIT_CS1)|(1<<BIT_CS2)|(1<<BIT_CS3)); CTRLPORT |= ((1<<BIT_CS0)|(1<<BIT_CS1)|(1<<BIT_CS2)|(1<<BIT_CS3));
timer0_on(); timer0_on();
timer2_on(); timer2_on();
DDRD |= 1<<PD7; //OC2 pin to output DDRD |= 1 << PD7; // OC2 pin to output
RDIMPORT |= (1<<BIT_RDIM); RDIMPORT |= (1 << BIT_RDIM);
RDIMDDR |= (1<<BIT_RDIM); RDIMDDR |= (1 << BIT_RDIM);
//Watchdog Timer aktivieren // activate watchdog timer
wdt_reset(); wdt_reset();
wdt_enable(0x00); // 17ms Watchdog wdt_enable(0x00); // 17ms watchdog
} }

View File

@ -1,4 +1,3 @@
#include "../config.h" #include "../config.h"
#include "../makros.h" #include "../makros.h"
@ -12,143 +11,127 @@
#define PIN_STR PB2 #define PIN_STR PB2
// buffer which holds the currently shown frame
//Der Puffer, in dem das aktuelle Bild gespeichert wird
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
//zur nächsten Zeile weiterschalten // switch to next row
inline void nextrow(uint8_t row){ static void nextrow(uint8_t row) {
// clear states of the preceding row
//Die Zustände von der vorherigen Zeile löschen
PORTC &= 0xF0; PORTC &= 0xF0;
PORTD &= 0x0F; PORTD &= 0x0F;
PORTB &= 0xFC; PORTB &= 0xFC;
//kurze Warteschleife, damit die Treiber auch wirklich ausschalten // short delay loop, to ensure proper deactivation of the drivers
unsigned char i; unsigned char i;
for(i=0;i<10;i++){ for (i = 0; i < 10; i++) {
asm volatile("nop"); asm volatile("nop");
} }
if (row == 0){ if (row == 0) {
//Zeile 0: Das erste Schieberegister initialisieren // row 0: initialize first shift register
PORTB &= ~(1<<PIN_DATA); // zeile ist aktiv auf low PORTB &= ~(1 << PIN_DATA); // row is active low
PORTB |= (1<<PIN_CLK); PORTB |= (1 << PIN_CLK);
PORTB &= ~(1<<PIN_CLK); PORTB &= ~(1 << PIN_CLK);
PORTB |= (1<<PIN_DATA); PORTB |= (1 << PIN_DATA);
} else {
// remaining rows: just shift forward
PORTB |= (1 << PIN_CLK);
PORTB &= ~(1 << PIN_CLK);
} }
else {
//In jeder anderen Zeile einfach nur einen weiter schieben // another delay loop, to ensure that the drivers are ready
PORTB |= (1<<PIN_CLK); for (i = 0; i < 20; i++) {
PORTB &= ~(1<<PIN_CLK);
}
//noch eine Warteschleife, damit die Zeilentreiber bereit sind
for(i=0;i<20;i++){
asm volatile("nop"); asm volatile("nop");
} }
} }
// display a row
static void rowshow(unsigned char row, unsigned char plane) {
// depending on the currently drawn plane, display the row for a specific
// amount of time
static unsigned char const tcnt0_table[] = {244, 236, 206};
TCNT0 = tcnt0_table[plane];
//Eine Zeile anzeigen // output data of the current row to the column drivers
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:
TCNT0 = 0x100-12;
break;
case 1:
TCNT0 = 0x100-20;
break;
case 2:
TCNT0 = 0x100-50;
}
uint8_t tmp, tmp1; uint8_t tmp, tmp1;
//die Daten für die aktuelle Zeile auf die Spaltentreiber ausgeben tmp = pixmap[plane][row][0];
tmp = pixmap[plane][row][0];
tmp1 = pixmap[plane][row][1]; tmp1 = pixmap[plane][row][1];
PORTC = ( PORTC & 0xF0 ) | (tmp & 0x0F); PORTC = (PORTC & 0xF0) | (tmp & 0x0F);
PORTD = ( PORTD & 0x0F ) | (tmp & 0xF0); PORTD = (PORTD & 0x0F) | (tmp & 0xF0);
PORTB = ( PORTB & 0xFC ) | (tmp1 & 0x03); PORTB = (PORTB & 0xFC) | (tmp1 & 0x03);
} }
//Dieser Interrupt wird je nach Ebene mit 50kHz 31,25kHz oder 12,5kHz ausgeführt // depending on the plane this interrupt gets triggered at 50 kHz, 31.25 kHz or
SIGNAL(SIG_OVERFLOW0) // 12.5 kHz
{ SIGNAL(SIG_OVERFLOW0) {
static unsigned char plane = 0; static unsigned char plane = 0;
static unsigned char row = 0; static unsigned char row = 0;
//Watchdog zurücksetzen // reset watchdog
wdt_reset(); wdt_reset();
//Zeile und Ebene inkrementieren // increment both row and plane
if(++plane==NUMPLANE){ if (++plane == NUMPLANE) {
plane=0; plane = 0;
if(++row == NUM_ROWS){ if (++row == NUM_ROWS) {
row = 0; row = 0;
} }
nextrow(row); nextrow(row);
} }
//Die aktuelle Zeile in der aktuellen Ebene ausgeben // output current row according to current plane
rowshow(row, plane); rowshow(row, plane);
} }
void timer0_off(){ void timer0_off() {
cli(); cli();
/* /*
COLPORT1 = 0; COLPORT1 = 0;
COLPORT2 = 0; COLPORT2 = 0;
ROWPORT = 0; ROWPORT = 0;
*/ */
TCCR0 = 0x00; TCCR0 = 0x00;
sei(); sei();
} }
// Den Timer, der denn Interrupt auslöst, initialisieren // initialize timer which triggers the interrupt
void timer0_on(){ static void timer0_on() {
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00 CS02 CS01 CS00
CS02 CS01 CS00 0 0 0 stop
0 0 0 stop 0 0 1 clk
0 0 1 clk 0 1 0 clk/8
0 1 0 clk/8 0 1 1 clk/64
0 1 1 clk/64 1 0 0 clk/256
1 0 0 clk/256 1 0 1 clk/1024
1 0 1 clk/1024 */
TCCR0 = 0x03; // clk/64
*/ TCNT0 = 0xFF - 20; // reset timer
TCCR0 = 0x03; // clk/64 TIMSK |= (1 << TOIE0); // compare match Interrupt on
TCNT0 = 0xFF-20; // reset timer
TIMSK |= (1<<TOIE0); // Compare match Interrupt on
} }
void borg_hw_init(){
// Nötige Pins auf Ausgang void borg_hw_init() {
DDRC=0x0F; // PC0-3 - Row 0-3 // set required pins to output mode
DDRD=0xF4; // PD4-7 - Row 4-7 PD2 - Masse für Joy DDRC = 0x0F; // PC0-3 - Row 0-3
DDRB=0x1F; // PB0-1 - Row 8-9 PB2-3 - STR, CLK, d DDRD = 0xF4; // PD4-7 - Row 4-7 PD2 - ground for joy
DDRB = 0x1F; // PB0-1 - Row 8-9 PB2-3 - STR, CLK, d
// Alle Spalten erstmal aus, clk aus, d und str an
// PC4-5, PD013 Pullup an // turn off all columns for now, clk off, d and str on
PORTC=0x30; // PC4-5, PD013 pullup on
PORTD=0x0B; PORTC = 0x30;
PORTB=0x14; PORTD = 0x0B;
PORTB = 0x14;
timer0_on(); timer0_on();
//Watchdog Timer aktivieren // activate watchdog timer
wdt_reset(); wdt_reset();
wdt_enable(0x00); // 17ms Watchdog wdt_enable(0x00); // 17ms watchdog
} }

View File

@ -1,4 +1,3 @@
#include "../config.h" #include "../config.h"
#include "../makros.h" #include "../makros.h"
#include "../ioport.h" #include "../ioport.h"
@ -9,29 +8,28 @@
#include "borg_hw.h" #include "borg_hw.h"
// buffer which holds the currently shown frame
//Der Puffer, in dem das aktuelle Bild gespeichert wird
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
//Eine Zeile anzeigen
inline void rowshow(unsigned char row){
//die Daten für die aktuelle Zeile auf die Spaltentreiber ausgeben
COLPORT1 = pixmap[0][row][0]; // display a row
COLPORT2 = pixmap[0][row][1]; inline void rowshow(unsigned char row) {
// output data of the current row to the column drivers
COLPORT1 = pixmap[0][row][0];
COLPORT2 = pixmap[0][row][1];
OUTPUT_ON(LATCH_R); OUTPUT_ON(LATCH_R);
OUTPUT_OFF(LATCH_R); OUTPUT_OFF(LATCH_R);
COLPORT1 = pixmap[1][row][0]; COLPORT1 = pixmap[1][row][0];
COLPORT2 = pixmap[1][row][1]; COLPORT2 = pixmap[1][row][1];
OUTPUT_ON(LATCH_G); OUTPUT_ON(LATCH_G);
OUTPUT_OFF(LATCH_G); OUTPUT_OFF(LATCH_G);
COLPORT1 = pixmap[2][row][0]; COLPORT1 = pixmap[2][row][0];
COLPORT2 = pixmap[2][row][1]; COLPORT2 = pixmap[2][row][1];
OUTPUT_ON(LATCH_B); OUTPUT_ON(LATCH_B);
OUTPUT_OFF(LATCH_B); OUTPUT_OFF(LATCH_B);
} }
@ -41,28 +39,29 @@ uint32_t mod = 1280000ul;
uint32_t akku; uint32_t akku;
unsigned char row = 0; unsigned char row = 0;
ISR(SIG_OUTPUT_COMPARE0) ISR(SIG_OUTPUT_COMPARE0)
{ {
//Watchdog zurücksetzen // reset watchdog
wdt_reset(); wdt_reset();
akku += mod; akku += mod;
OCR1A = akku / 256; OCR1A = akku / 256;
rowshow(row); rowshow(row);
if(++row == NUM_ROWS){ if (++row == NUM_ROWS) {
row = NUM_ROWS - 1; row = NUM_ROWS - 1;
} }
} }
ISR(INT0_vect){
if(akku > (64ul * 256ul * 64ul)){ ISR(INT0_vect) {
if (akku > (64ul * 256ul * 64ul)) {
akku -= OCR1A - TCNT1; akku -= OCR1A - TCNT1;
mod = akku / 64; mod = akku / 64;
akku = 0; akku = 0;
row = 0; row = 0;
@ -72,32 +71,31 @@ ISR(INT0_vect){
} }
void timer0_off(){ void timer0_off() {
cli(); cli();
TCCR1B = 0x00; TCCR1B = 0x00;
sei(); sei();
} }
// Den Timer, der denn Interrupt auslöst, initialisieren // initialize timer which triggers the interrupt
void timer1_on(){ void timer1_on() {
TCCR1B = 1; //clk/1 TCCR1B = 1; // clk/1
TIMSK |= (1<<OCIE1A); TIMSK |= (1 << OCIE1A);
} }
void borg_hw_init(){
void borg_hw_init() {
DDR(COLPORT1) = 0xff; DDR(COLPORT1) = 0xff;
DDR(COLPORT2) = 0xff; DDR(COLPORT2) = 0xff;
SET_DDR(LATCH_R); SET_DDR(LATCH_R);
SET_DDR(LATCH_G); SET_DDR(LATCH_G);
SET_DDR(LATCH_B); SET_DDR(LATCH_B);
timer1_on(); timer1_on();
//Watchdog Timer aktivieren // activate watchdog timer
wdt_reset(); wdt_reset();
wdt_enable(0x00); // 17ms Watchdog wdt_enable(0x00); // 17ms watchdog
} }

View File

@ -146,25 +146,13 @@ void tetris_std_removedLines(void *pVariantData,
tetris_standard_variant_t *pStdVariant = tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData; (tetris_standard_variant_t *)pVariantData;
uint8_t nLines = tetris_bucket_calculateLines(nRowMask); uint8_t nLines = tetris_bucket_calculateLines(nRowMask);
assert(nLines <= 4);
pStdVariant->nLines += nLines; pStdVariant->nLines += nLines;
pStdVariant->nLevel = ((pStdVariant->nLines / 10) < TETRIS_INPUT_LEVELS) ? pStdVariant->nLevel = ((pStdVariant->nLines / 10) < TETRIS_INPUT_LEVELS) ?
(pStdVariant->nLines / 10) : (TETRIS_INPUT_LEVELS - 1); (pStdVariant->nLines / 10) : (TETRIS_INPUT_LEVELS - 1);
switch (nLines) static uint16_t const nScoreTable[] PROGMEM = {0, 50, 150, 250, 400};
{ pStdVariant->nScore += pgm_read_word(&nScoreTable[nLines]);
case 1:
pStdVariant->nScore += 50;
break;
case 2:
pStdVariant->nScore += 150;
break;
case 3:
pStdVariant->nScore += 250;
break;
case 4:
pStdVariant->nScore += 400;
break;
}
} }