Ping-Pong на AVR

    В очередную уборку в мастерской довелось мне наткнуться на два матричных индикатора 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();         
          }
    }
    
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 11

      +10
      Картинки не грузятся.
      Вместо статьи — код программы, место которому — на гитхабе или в пастебине.
      Комментарии на буржуйском.

      Убирай в черновики срочно, пока карму не слили!
        +1
        UPD: Теперь картинки показываются, но стало еще хуже.
        Такие большие картинки надо под кат прятать.
          +7
          И ссылка на видио только для зарегистрированных вконтактике.
          Вот меня там нет, например. Я должен регистрироваться, чтобы посмотреть полминуты видео?
          +3
          «Радикал» — как корабль назовешь…
            +5
            Видео которое просит регистрации и простыня кода, оформление отвратительно.
              +2
              У компа выиграть нельзя при таких условиях.
              Переосмысление Понг в жанре survival?
                +2
                Шикарная идея :)

                Если кому-то захочется поиграть, то вот, запилил убогую браузерную версию на процессинге: linux-users.ru/d/
                  +1
                  Как-то грустно получилось… быстро умираешь)))))
                0
                Мне кажется, или игра на видео иногда подвисает?
                  0
                  По поводу кода — как-то много операций напихано в прерывание. Насколько я знаю, это не очень хорошо.
                    0
                    В случае, если контроллер дёргает много прерываний, а впрерываниях вызываются процедуры, плюс одно и тоже прерывание может быть вызвано дважды, до завершения обработки, приводит к тяжёлым и сложноотлавливаемым багам. Например срыву стека. Если сюда добавить использование глобальных переменных на пару с отсутствием volatile, то происходит тихий ужас. На прошлой неделе вылавливал такую багу как раз. Упростил обработчик до предела.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое