В очередную уборку в мастерской довелось мне наткнуться на два матричных индикатора 8х8, там же была найдена Mega16, кнопки, макетка. «Какой же ты программист, если за свою жизнь ни разу не написал Тетрис?», спросил мозг.
Конец дня был посвящен тому, чтобы навесом спаять это все хозяйство.



Схема выглядит следующим образом:



К сожалению руки до Тетриса пока не дошли, размялся тем, что написал Пинг-Понг.
Видео работы устройства можно посмотреть тут (видео).

/*****************************************************
Chip type               : ATmega16
Program type            : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/

#include <mega16.h>
#include <delay.h>
#include <math.h>
#include <stdlib.h> 
#include <stdio.h>

int cnt = 0;
char src = 0, start = 0, tmp = 0, cx = 3, cy = 14, mx = 2, my = 15, ex = 3, ey = 0, dx = 1, dy = 1, fld[16][8], speed = 200;
char flds[16][8] = {{0,1,1,1,1,1,1,0},   // 0
                   {1,0,0,0,0,0,0,1},   // 1
                   {1,0,1,0,0,1,0,1},   // 2
                   {1,0,0,0,0,0,0,1},   // 3
                   {1,0,1,0,0,1,0,1},   // 4
                   {1,0,0,1,1,0,0,1},   // 5
                   {0,1,0,0,0,0,1,0},   // 6
                   {0,0,1,1,1,1,0,0},   // 7
                   
                   {0,0,0,0,0,0,0,0},   // 8
                   {0,0,0,0,0,0,0,0},   // 9
                   {0,0,0,0,0,0,0,0},   // 10
                   {0,0,0,0,0,0,0,0},   // 11
                   {0,0,0,0,0,0,0,0},   // 12
                   {0,0,0,0,0,0,0,0},   // 13
                   {0,0,0,0,0,0,0,0},   // 14
                   {0,0,0,0,0,0,0,0}};  // 15   
                   
void showsrc(void) {
char x = 0, y = 0;
    src = 0, start = 0, tmp = 0, cx = 3, cy = 14, mx = 2, my = 15, ex = 3, ey = 0, dx = 1, dy = 1, speed = 200;
    while (y < 16) { 
        x = 0;
        while (x < 8) {
            fld[y][x] = flds[y][x];
            x++;
        }
        y++;
    }
}
                              
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Place your code here
    if (cnt >= speed) {
        if (start == 0) 
        {       
            fld[9][5]  = 0; fld[10][5] = 0;
            fld[11][5] = 0; fld[12][5] = 0; 
            fld[12][3] = 0; fld[12][7] = 0;
            fld[13][3] = 0; fld[13][5] = 0;
            fld[13][7] = 0; fld[13][4] = 0;
            fld[13][6] = 0; fld[14][4] = 0;
            fld[14][5] = 0; fld[14][6] = 0;
            fld[15][5] = 0;
            if (tmp == 0) { 
                fld[10][5] = 1; fld[11][5] = 1;
                fld[12][5] = 1; fld[13][3] = 1;
                fld[13][5] = 1; fld[13][7] = 1;
                fld[14][4] = 1; fld[14][5] = 1;
                fld[14][6] = 1; fld[15][5] = 1;           
            }
            else {
                fld[9][5]  = 1; fld[10][5] = 1;
                fld[11][5] = 1; fld[12][3] = 1;
                fld[12][5] = 1; fld[12][7] = 1;
                fld[13][4] = 1; fld[13][5] = 1;
                fld[13][6] = 1; fld[14][5] = 1;      
            };
            tmp++;
            if (tmp == 2) tmp = 0; 
        }
        else //game cycle
        {   
            fld[cy][cx] = 0;
            if (dy == 1) {
                if (cy > 0) cy--; 
                else {tmp = 0; start = 0; showsrc();}
            }
            else {
                if (cy < 15) cy ++;
                else {tmp = 0; start = 0; showsrc();}
            }      
            if ((cy == 1) && (fld[0][cx] == 1)) dy = 2;
            if ((cy == 1) && (fld[0][cx] == 0)) {tmp = 0; start = 0; showsrc();}  
            if ((cy == 14) && (fld[15][cx] == 1)) dy = 1;
            if ((cy == 14) && (fld[0][cx] == 0)) {tmp = 0; start = 0; showsrc();} 
            if (start == 1) {           
                if (dx == 1) {
                    cx--;
                    if (cx == 0) {dx = 2;} 
                }
                else {
                    cx++;
                    if (cx == 7) {dx = 1;}
                }
                fld[cy][cx] = 1;      
                if (PINC.7 == 0) {
                    delay_ms(1);
                    if (PINC.7 == 0) {
                        if ((mx > 0) && (mx != 0)) {mx--; fld[my][mx+3] = 0;}
                    }
                }    
                if (PINC.6 == 0) {
                    delay_ms(1);
                    if (PINC.6 == 0){ 
                        if ((mx < 5) && (mx != 5)) {mx++; fld[my][mx-1] = 0;}
                    }  
                } 
                ex = cx;
                if (cx > 5) ex = 5; 
                if (ex > 0) fld[ey][ex-1] = 0; 
                if (ex < 5) fld[ey][ex+3] = 0;
                fld[my][mx] = 1; fld[my][mx+1] = 1; fld[my][mx+2] = 1; 
                fld[ey][ex] = 1; fld[ey][ex+1] = 1; fld[ey][ex+2] = 1;
            }                     
        } 
    cnt = 0;    
    }
    cnt++;
}

void paint(void)
{
char x = 0;
    while (x <= 7) {
        PORTA = 0b00000000;
        PORTB = 0b00000000;
        PORTD = 0b11111111;
        if (src == 0) {
            PORTA.0 = fld[0][x];  PORTA.1 = fld[1][x];
            PORTA.2 = fld[2][x];  PORTA.3 = fld[3][x];
            PORTA.4 = fld[4][x];  PORTA.5 = fld[5][x];
            PORTA.6 = fld[6][x];  PORTA.7 = fld[7][x];
        } else {    
            PORTB.0 = fld[8][x];  PORTB.1 = fld[9][x];
            PORTB.2 = fld[10][x]; PORTB.3 = fld[11][x];
            PORTB.4 = fld[12][x]; PORTB.5 = fld[13][x];
            PORTB.6 = fld[14][x]; PORTB.7 = fld[15][x];
        }    
        switch (x) {
            case 0: {PORTD = 0b11111110; break;} case 1: {PORTD = 0b11111101; break;}
            case 2: {PORTD = 0b11111011; break;} case 3: {PORTD = 0b11110111; break;}
            case 4: {PORTD = 0b11101111; break;} case 5: {PORTD = 0b11011111; break;}
            case 6: {PORTD = 0b10111111; break;} case 7: {PORTD = 0b01111111; break;}
        }    
        delay_us(50);
        x++;
    }
    src++;
    if (src == 2) src = 0; 
}

void initgame(void) {
char x = 0, y = 0;
    #asm("cli")
    while (y < 16) { 
        x = 0;
        while (x < 8) {
            fld[y][x] = 0;
            x++;
        }
        y++;
    } 
    tmp = 1; 
    speed = 50;
    #asm("sei")
}

void inkey(void){
char key = 0;
    if (PINC.1 == 0) {
        delay_ms(1);
        if (PINC.1 == 0) key = 3;
    } 
    if (PINC.0 == 0) {
        delay_ms(1);
        if (PINC.0 == 0) key = 4;
    }   
    switch (key) {
    case 1: {
    
        break;}
    case 2: {

        break;}
    case 3: {

        break;}
    case 4: {
        if (start == 0) {
            start = 1;
            initgame();
        }    
        break;} 
    default: {
    }
    };         
} 

void main(void)
{
PORTA=0x00;
DDRA=0xFF;
PORTB=0x00;
DDRB=0xFF;
PORTC=0xFF;
DDRC=0x00;
PORTD=0x00;
DDRD=0xFF;
TCCR0=0x02;
TCNT0=0x00;
OCR0=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
MCUCR=0x00;
MCUCSR=0x00;
TIMSK=0x01;
UCSRB=0x00;
ACSR=0x80;
SFIOR=0x00;
ADCSRA=0x00;
SPCR=0x00;
TWCR=0x00;
showsrc();
#asm("sei")
while (1)
      {
      paint();
      inkey();         
      }
}