Code:
/* Definiert die Frequenz */
#define F_CPU 16000000UL
/* Umbennung der Eingabe ( Taster ) */
#define TASTER_1 (!(PIND & (1<<PD5))
#define TASTER_2 (!(PIND & (1<<PD6))
#define TASTER_3 (!(PIND & (1<<PD3))
#define TASTER_4 (!(PIND & (1<<PD4))
/* USB Ladeerkennung */
#define USB_CONNECTED PINB & (1<<PINB4)
/* Akku muss geladen werden */
#define ACCU_MUST_LOADING (!(PIND & (1<<PIND7)))
/* Summer */
#define SUMMER_AUS PORTC |= (1<<PC2)
#define SUMMER_AN PORTC &= ~(1<<PC2)
#define SUMMER_TOGGLE PORTC ^= (1<<PC2)
/* Richtung zum schieben der Anzeige */
#define RIGHT 1
#define LEFT 0
/* Schwelle für AutoOFF ( 6000 = 1 min. ) */
#define AUTO_OFF 6000
/* Verhindert ein drücken während des Betriebes */
#define INTERRUPT_INT0_DISABLE GICR &= ~(1<<INT0)
#define INTERRUPT_INT0_ENABLE GICR |= (1<<INT0)
/* Benötigte Bibliotheken */
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include "avr/pgmspace.h"
#include "avr/sleep.h"
#include <string.h>
/* Grafiken */
const char charMap[71][8] PROGMEM ={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // an
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, // aus
{0xC3,0x99,0x99,0x99,0x99,0x99,0xC3,0xFF}, // null
{0xE7,0xC7,0xE7,0xE7,0xE7,0xE7,0xE7,0xFF}, // eins
{0xC3,0x99,0xF9,0xF3,0xE7,0xCF,0x81,0xFF}, // zwei
{0xC3,0x99,0xF9,0xE3,0xF9,0x99,0xC3,0xFF}, // drei
{0xF3,0xE3,0xC3,0x93,0x81,0xF3,0xF3,0xFF}, // vier
{0x81,0x9F,0x83,0xF9,0xF9,0x99,0xC3,0xFF}, // fünf
{0xE3,0xCF,0x9F,0x83,0x99,0x99,0xC3,0xFF}, // sechs
{0x81,0xF9,0xF9,0xF3,0xE7,0xE7,0xE7,0xFF}, // sieben
{0xC3,0x99,0x99,0xC3,0x99,0x99,0xC3,0xFF}, // acht
{0xC3,0x99,0x99,0xC1,0xF9,0xF3,0xC7,0xFF}, // neun
{0xe7,0xdb,0xdb,0xdb,0xdb,0xc3,0xdb,0xdb}, // A
{0x87,0xbb,0xbb,0xbb,0x87,0xbb,0xbb,0x87}, // B
{0xC3,0x99,0x3F,0x3F,0x3F,0x99,0xC3,0xFF}, // C
{0x87,0x93,0x99,0x99,0x99,0x93,0x87,0xFF}, // D
{0x81,0x9F,0x9F,0x87,0x9F,0x9F,0x81,0xFF}, // E
{0x81,0x9F,0x9F,0x87,0x9F,0x9F,0x9F,0xFF}, // F
{0xC3,0x99,0x3F,0x3F,0x31,0x99,0xC1,0xFF}, // G
{0x99,0x99,0x99,0x81,0x99,0x99,0x99,0xFF}, // H
{0xE7,0xE7,0xE7,0xE7,0xE7,0xE7,0xE7,0xFF}, // I
{0xF9,0xF9,0xF9,0xF9,0x99,0x99,0xC3,0xFF}, // J
{0x99,0x99,0x93,0x87,0x93,0x99,0x99,0xFF}, // K
{0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x81,0x81}, // L
{0x39,0x11,0x01,0x01,0x29,0x39,0x39,0xFF}, // M
{0x39,0x19,0x09,0x21,0x31,0x39,0x39,0xFF}, // N
{0xC3,0x99,0x99,0x99,0x99,0x99,0xC3,0xFF}, // O
{0x83,0x99,0x99,0x83,0x9F,0x9F,0x9F,0xFF}, // P
{0xC3,0x99,0x99,0x99,0x91,0xC3,0xF1,0xFF}, // Q
{0x83,0x99,0x99,0x83,0x93,0x99,0x99,0xFF}, // R
{0xC3,0x99,0x8F,0xC7,0xF1,0x99,0xC3,0xFF}, // S
{0x81,0xE7,0xE7,0xE7,0xE7,0xE7,0xE7,0xFF}, // T
{0x99,0x99,0x99,0x99,0x99,0x99,0xC1,0xFF}, // U
{0x99,0x99,0x99,0x99,0x99,0xC3,0xE7,0xFF}, // V
{0x39,0x39,0x39,0x29,0x01,0x11,0x39,0xFF}, // W
{0x99,0x99,0xC3,0xE7,0xC3,0x99,0x99,0xFF}, // X
{0x99,0x99,0x99,0xC3,0xE7,0xE7,0xE7,0xFF}, // Y
{0x01,0xF9,0xF3,0xE7,0xCF,0x9F,0x01,0xFF}, // Z
{0xFF,0xFF,0xC3,0xF9,0xC1,0x99,0xC5,0xFF}, // a
{0x9F,0x9F,0x9F,0x83,0x99,0x99,0xA3,0xFF}, // b
{0xFF,0xFF,0xC3,0x99,0x9F,0x99,0xC3,0xFF}, // c
{0xF9,0xF9,0xF9,0xC1,0x99,0x99,0xC5,0xFF}, // d
{0xFF,0xFF,0xC3,0x99,0x81,0x9F,0xC3,0xFF}, // e
{0xE3,0xC9,0xCF,0x87,0xCF,0xCF,0xCF,0xFF}, // f
{0xFF,0xFF,0xC5,0x99,0x99,0xC1,0xF9,0xC3}, // g
{0x9F,0x9F,0x93,0x89,0x99,0x99,0x99,0xFF}, // h
{0xE7,0xFF,0xE7,0xE7,0xE7,0xE7,0xE7,0xFF}, // i
{0xF3,0xFF,0xF3,0xF3,0xF3,0x33,0x33,0x87}, // j
{0x9F,0x9F,0x99,0x93,0x87,0x93,0x99,0xFF}, // k
{0xE7,0xE7,0xE7,0xE7,0xE7,0xE7,0xE7,0xFF}, // l
{0xFF,0xFF,0x39,0x11,0x01,0x29,0x39,0xFF}, // m
{0xFF,0xFF,0x83,0x99,0x99,0x99,0x99,0xFF}, // n
{0xFF,0xFF,0xC3,0x99,0x99,0x99,0xC3,0xFF}, // o
{0xFF,0xFF,0xA3,0x99,0x99,0x83,0x9F,0x9F}, // p
{0xFF,0xFF,0xC5,0x99,0x99,0xC1,0xF9,0xF9}, // q
{0xFF,0xFF,0xA3,0x89,0x9F,0x9F,0x9F,0xFF}, // r
{0xFF,0xFF,0xC1,0x9F,0xC3,0xF9,0x83,0xFF}, // s
{0xCF,0xCF,0x83,0xCF,0xCF,0xCB,0xE7,0xFF}, // t
{0xFF,0xFF,0x99,0x99,0x99,0x99,0xC5,0xFF}, // u
{0xFF,0xFF,0x99,0x99,0x99,0xC3,0xE7,0xFF}, // v
{0xFF,0xFF,0x39,0x29,0x01,0x01,0x93,0xFF}, // w
{0xFF,0xFF,0x39,0x93,0xC7,0x93,0x39,0xFF}, // x
{0xFF,0xFF,0x99,0x99,0x99,0xC1,0xF9,0xC3}, // y
{0xFF,0xFF,0x81,0xF3,0xE7,0xCF,0x81,0xFF}, // z
{0x81,0x7E,0x5A,0x7E,0x42,0x66,0x7E,0x81}, // Smiley
{0xFF,0xE7,0xC3,0xDB,0xDB,0xDB,0xDB,0xC3}, // Battery (leer)
{0xFF,0xE7,0xC3,0xDB,0xDB,0xDB,0xC3,0xC3}, // Battery ( mit einem Strich )
{0xFF,0xE7,0xC3,0xDB,0xDB,0xC3,0xC3,0xC3}, // Battery ( mit zwei Strichen )
{0xFF,0xE7,0xC3,0xDB,0xC3,0xC3,0xC3,0xC3}, // Battery ( mit drei Strichen )
{0xFF,0xE7,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3}, // Battery ( mit vier Strichen )
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF} // Punkt für´s www(.)
};
const char Spieler_links[7][8] PROGMEM ={
{0xFF,0xFF,0xFD,0x80,0x80,0xFF,0xFF,0xFF}, // eins
{0xFF,0xBD,0x9C,0x8E,0xA6,0xB0,0xB9,0xFF}, // zwei
{0xFF,0xDD,0x9C,0xB6,0xB6,0x80,0xC9,0xFF}, // drei
{0xFF,0xE7,0xE3,0xE9,0x80,0x80,0xEF,0xFF}, // vier
{0xFF,0xD8,0x98,0xBA,0xBA,0x82,0xC6,0xFF}, // füns
{0xFF,0xC3,0x81,0xB4,0xB6,0x86,0xCF,0xFF} // sechs
};
const char Spieler_rechts[7][8] PROGMEM ={
{0xFF,0xE7,0xE7,0xE7,0xE7,0xE7,0xE3,0xE7},
{0xFF,0x81,0xF3,0xE7,0xCF,0x9F,0x99,0xC3},
{0xFF,0xC3,0x99,0x9F,0xC7,0x9F,0x99,0xC3},
{0xFF,0xCF,0xCF,0x81,0xC9,0xC3,0xC7,0xCF},
{0xFF,0xC3,0x99,0x9F,0x9F,0xC1,0xF9,0x81},
{0xFF,0xC3,0x99,0x99,0xC1,0xF9,0xF3,0xC7}
};
const char Spieler_gegenueber[7][8] PROGMEM ={
{0xFF,0xFF,0xFF,0x01,0x01,0xBF,0xFF,0xFF},
{0xFF,0x9D,0x0D,0x65,0x71,0x39,0xBD,0xFF},
{0xFF,0x93,0x01,0x6D,0x6D,0x39,0xBB,0xFF},
{0xFF,0xF7,0x01,0x01,0x97,0xC7,0xE7,0xFF},
{0xFF,0x63,0x41,0x5D,0x5D,0x19,0x1B,0xFF},
{0xFF,0xF3,0x61,0x6D,0x2D,0x81,0xC3,0xFF}
};
uint8_t VRAM[50] = { };
uint8_t USB_STATE = 0;
uint16_t AUTO_OFF_Counter = 0;
uint16_t CharacterIndexValue = 0;
void clear_screen();
void fill_screen();
void check_usb();
void Display_all_Symbols();
uint8_t GetCharacterIndex(char a);
void ShiftVRAM(uint8_t direction, uint16_t ms);
void StringtoCharacter(const char *s);
void check_ACCU();
void check_AUTO_OFF();
void DisplayString(uint16_t x, const char *s);
int main(void)
{
DDRA |= ((1<<PA0) | (1<<PA1) | (1<<PA2) | (1<<PA3) | (1<<PA4) | (1<<PA5) | (1<<PA6) | (1<<PA7));
DDRB |= ((1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3) | (1<<PB5) | (1<<PB6) | (1<<PB7));
DDRC |= ((1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5) | (1<<PC6) | (1<<PC7));
/* TIMER0 CompareMatch (Multiplexen der Anzeige) */
TCCR0 |= (1<<WGM01) | (1<<WGM00) | (1<<CS01) | (1<<CS00);
TIMSK |= (1<<OCIE0);
/* Timer 1 Initalisieren */
TCCR1B |= ((1<<CS12) | (1<<CS10)); // Teiler auf 1028
TCCR1B |= (1<<WGM12); // CTC = ClearTimerCompare
OCR1A = 77; // ca. jede 10 ms. ein Überlauf
TIMSK |= (1<<OCIE1A);
/* Interrupt "0" aktivieren */
GICR |= (1<<INT0);
/* Muss ausgeschaltet werden, weil der Summer sonst dauernd an ist */
SUMMER_AUS;
/* Interrupts global erlauben */
sei();
while(1)
{
INTERRUPT_INT0_DISABLE;
check_usb();
check_ACCU();
check_AUTO_OFF();
if (USB_STATE == 0)
{
Display_all_Symbols();
}
}// Ende While
}// Ende Main
/* Multiplexen der Anzeige */
ISR(TIMER0_COMP_vect)
{
static volatile uint8_t spalte = 0;
PORTC &= ~((1<<PC7) | (1<<PC6) | (1<<PC5) | (1<<PC4) | (1<<PC3));
PORTB &= ~((1<<PB2) | (1<<PB1) | (1<<PB0));
// neue Zeilendaten ausgeben
PORTA = VRAM[spalte];
// Spalte aktivieren
switch (spalte) {
case 0: PORTC |= (1<<PC3);
break;
case 1: PORTC |= (1<<PC4);
break;
case 2: PORTC |= (1<<PC5);
break;
case 3: PORTC |= (1<<PC6);
break;
case 4: PORTC |= (1<<PC7);
break;
case 5: PORTB |= (1<<PB2);
break;
case 6: PORTB |= (1<<PB1);
break;
case 7: PORTB |= (1<<PB0);
break;
default: break;
}
spalte++; // nächste Spalte
if (spalte >= 8) spalte = 0; // Spalten 0..7
}
/* Jede 10 ms wird hier die Variable "Save_Value_Counter" um + 1 erhöht */
ISR (TIMER1_COMPA_vect)
{
AUTO_OFF_Counter = AUTO_OFF_Counter + 1;
}
/* Aufwecken des Gerätes */
ISR (INT0_vect)
{
SUMMER_AN;
_delay_ms(1);
SUMMER_AUS;
}
/* Löschen des aktuellen Displays */
void clear_screen(void)
{
for(uint8_t i = 0 ; i < 8 ; i++)
{
VRAM[i] = 0xFF;
}
}
/* Display komplett anschalten */
void fill_screen(void)
{
for (uint8_t i = 0 ; i < 8 ; i++)
{
VRAM[i] = 0x00;
}
}
/* Checkt ob Maxi Dice mit USB Verbunden ist */
void check_usb(void)
{
if (USB_CONNECTED)
{
USB_STATE = 1;
for (uint8_t i = 65 ; i < 70 ; i++)
{
for (uint8_t d= 0 ; d < 8 ; d++)
{
VRAM[d] = pgm_read_byte(&charMap[i][d]);
}
_delay_ms(500);
}
}
else
{
USB_STATE = 0;
}
}
/* Routine um das gesamte Grafikaray da zu stellen */
void Display_all_Symbols()
{
if (USB_STATE == 0)
{
for (uint8_t i = 0 ; i < 70 ; i++)
{
for (uint8_t d= 0 ; d < 8 ; d++)
{
VRAM[d] = pgm_read_byte(&charMap[i][d]);
}
check_usb();
_delay_ms(500);
}// Ende for
}
}
/* Errechnet den Index des aktuellen Zeichens */
uint8_t GetCharacterIndex(char a)
{
uint8_t index = 1; // alles aus
if ((a >= '0') && (a <= '9'))
index = a+2-48; // erste Zahl ist Index in der Tabelle des ersten Zeichens, zweite Zahl ist Index in Ascii Code des ersten Zeichens
else if ((a >= 'A') && (a <= 'Z'))
index = a+12-65;
else if ((a >= 'a') && (a <= 'z'))
index = a+38-97;
else if ((a == '.'))
index = a+70-46;
return index;
}
/* Schiebt den gesamten Zwischenspeicher (VRAM) des Zeichens */
void ShiftVRAM(uint8_t direction, uint16_t ms)
{
if (direction == 1)
{
for (uint8_t d= 0 ; d < 8 ; d++)
{
VRAM[0] = VRAM[0] >> 1 | 0x80;
VRAM[1] = VRAM[1] >> 1 | 0x80;
VRAM[2] = VRAM[2] >> 1 | 0x80;
VRAM[3] = VRAM[3] >> 1 | 0x80;
VRAM[4] = VRAM[4] >> 1 | 0x80;
VRAM[5] = VRAM[5] >> 1 | 0x80;
VRAM[6] = VRAM[6] >> 1 | 0x80;
VRAM[7] = VRAM[7] >> 1 | 0x80;
for (uint16_t i = 0; i < ms ; i++ )
{
_delay_ms(1);
}
}
}
else if (direction == 0)
{
for (uint8_t d= 0 ; d < 8 ; d++)
{
VRAM[0] = VRAM[0] << 1 | 0x01;
VRAM[1] = VRAM[1] << 1 | 0x01;
VRAM[2] = VRAM[2] << 1 | 0x01;
VRAM[3] = VRAM[3] << 1 | 0x01;
VRAM[4] = VRAM[4] << 1 | 0x01;
VRAM[5] = VRAM[5] << 1 | 0x01;
VRAM[6] = VRAM[6] << 1 | 0x01;
VRAM[7] = VRAM[7] << 1 | 0x01;
for (uint16_t i = 0; i < ms ; i++ )
{
_delay_ms(1);
}
}
}
}
/* Übergibt den String der Routine "GetCharacterIndex" */
void StringtoCharacter(const char *s)
{
while (*s)
CharacterIndexValue = GetCharacterIndex(*s++);
}
/* Überprüft ob Akku leer ist */
void check_ACCU(void)
{
clear_screen();
if ((ACCU_MUST_LOADING))
{
for (uint8_t i = 65 ; i < 66 ; i++)
{
for (uint8_t d= 0 ; d < 8 ; d++)
{
VRAM[d] = pgm_read_byte(&charMap[i][d]);
}
check_usb();
_delay_ms(500);
}// Ende for
clear_screen();
_delay_ms(500);
}
}
/* Funktion für AutoOff */
void check_AUTO_OFF(void)
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli();
if (AUTO_OFF_Counter >= AUTO_OFF)
{
INTERRUPT_INT0_ENABLE;
AUTO_OFF_Counter = 0;
SUMMER_AN;
_delay_ms(4);
SUMMER_AUS;
sleep_enable();
sei();
clear_screen();
sleep_cpu();
sleep_disable();
INTERRUPT_INT0_DISABLE;
}
sei();
}
Lesezeichen