/***************************************** Displays sample video of Mario Running Created by: Tom Gowing and Brian Pescatore *****************************************/ #include #include #include #include #include "uart.h" #include FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW); #define OUT_PORT PORTC #define OUT_DDR DDRC #define WAIT_TIME 1000 #define CYCLE_MODE 0 #define PRESS_MODE 1 #define _R 0xE0 //Red #define _G 0x1C //Green #define _B 0x03 //Blue #define _Y 0xFC //Yellow #define _M 0xE3 //Magenta #define _C 0x1F //Cyan #define _K 0x00 //Black #define _W 0xFF //White #define _N 0x25 //Brown #define _S 0xF5 //Mario's Skin #include "mario.h" #define BLAST_RLD "out 0x08, r18 \n\r"\ "out 0x08, r16 \n\r"\ "ld r16, Z+ \n\r" #define BLAST1 "out 0x08, r18 \n\r"\ "out 0x08, r16 \n\r"\ "nop \n\r"\ "out 0x08, r18 \n\r" #define BLAST4 BLAST1 \ BLAST1 \ BLAST1 \ BLAST1 #define COLOR16 BLAST_RLD \ BLAST4 \ BLAST4 \ BLAST4 \ BLAST1 \ BLAST1 volatile char display; char disp; volatile int line = 1; char offset = 0; char transmit_flag; volatile char controller = 0; #define _NOP asm volatile("NOP") #define NOP4 _NOP;_NOP;_NOP;_NOP #define NOP15 NOP4;NOP4;NOP4;_NOP;_NOP;_NOP #define PAUSE NOP15;NOP15;NOP15;NOP15 char STAND_R[16][16]; //Standing Facing Right char RUN_1_R[16][16]; //Running Right (Frame 1) char RUN_2_R[16][16]; //Running Right (Frame 2) char RUN_3_R[16][16]; //Running Right (Frame 3) char TURN_R[16][16]; //Turning from Left to Right char STAND_L[16][16]; //Standing Still facing Left char RUN_1_L[16][16]; //Running Left (Frame 1) char RUN_2_L[16][16]; //Running Left (Frame 2) char RUN_3_L[16][16]; //Running Left (Frame 3) char TURN_L[16][16]; //Turning from Right to Left volatile signed int time=0; //Determines time delay between switching frames char picture=0; char row = 0; //Array of screens for video loop char video[2][6] = {0,1,2,3,2,4, 5,6,7,8,7,9}; char* pixel_ptr; // Blasts out, a full scanline starting with the pixel indicated at memory ptr. void push_pixel(char* ptr) { asm volatile ( "mov r30, r24 \n\r" "mov r31, r25 \n\r" "ldi r18, 0x00 \n\r" COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 COLOR16 "out 0x08, r18 \n\r" ); } ISR (INT0_vect) { line++; // Determine which vertical pixel we are using int temp = line>>4; // Select the image which we want to display. switch(picture){ case 0: pixel_ptr = (STAND_R[temp]);break; case 1: pixel_ptr = (RUN_1_R[temp]);break; case 2: pixel_ptr = (RUN_2_R[temp]);break; case 3: pixel_ptr = (RUN_3_R[temp]);break; case 4: pixel_ptr = (TURN_L[temp]);break; case 5: pixel_ptr = (STAND_L[temp]);break; case 6: pixel_ptr = (RUN_1_L[temp]);break; case 7: pixel_ptr = (RUN_2_L[temp]);break; case 8: pixel_ptr = (RUN_3_L[temp]);break; case 9: pixel_ptr = (TURN_R[temp]);break; } if (PIND & 0x80) { push_pixel(pixel_ptr); time++; return; } line = 0; } void create_pixel_section(char PIX[16][16],char x,char y,char* pattern0, char* pattern1) { // Creates the pixel map in using (slow) methods on values that would be retrieved from memory. // This is same method in which the NES would calculate the pixels, but would be done using hardware. int i,c; for (i=0;i<8;i++) { c = (pattern1[i] & 0x80) ? 2 : 0; c+= (pattern0[i] & 0x80) ? 1 : 0; PIX[i+8*x][0+y*8] = palette[c]; c = (pattern1[i] & 0x40) ? 2 : 0; c+= (pattern0[i] & 0x40) ? 1 : 0; PIX[i+8*x][1+y*8] = palette[c]; c = (pattern1[i] & 0x20) ? 2 : 0; c+= (pattern0[i] & 0x20) ? 1 : 0; PIX[i+8*x][2+y*8] = palette[c]; c = (pattern1[i] & 0x10) ? 2 : 0; c+= (pattern0[i] & 0x10) ? 1 : 0; PIX[i+8*x][3+y*8] = palette[c]; c = (pattern1[i] & 0x08) ? 2 : 0; c+= (pattern0[i] & 0x08) ? 1 : 0; PIX[i+8*x][4+y*8] = palette[c]; c = (pattern1[i] & 0x04) ? 2 : 0; c+= (pattern0[i] & 0x04) ? 1 : 0; PIX[i+8*x][5+y*8] = palette[c]; c = (pattern1[i] & 0x02) ? 2 : 0; c+= (pattern0[i] & 0x02) ? 1 : 0; PIX[i+8*x][6+y*8] = palette[c]; c = (pattern1[i] & 0x01) ? 2 : 0; c+= (pattern0[i] & 0x01) ? 1 : 0; PIX[i+8*x][7+y*8] = palette[c]; } } void create_pixel_section_flip(char PIX[16][16],char x,char y,char* pattern0, char* pattern1) { // Creates the pixel map in using (slow) methods on values that would be retrieved from memory. int i,c; y = 1-y; //flip over vertical axis for (i=0;i<8;i++) { c = (pattern1[i] & 0x80) ? 2 : 0; c+= (pattern0[i] & 0x80) ? 1 : 0; PIX[i+8*x][7+y*8] = palette[c]; c = (pattern1[i] & 0x40) ? 2 : 0; c+= (pattern0[i] & 0x40) ? 1 : 0; PIX[i+8*x][6+y*8] = palette[c]; c = (pattern1[i] & 0x20) ? 2 : 0; c+= (pattern0[i] & 0x20) ? 1 : 0; PIX[i+8*x][5+y*8] = palette[c]; c = (pattern1[i] & 0x10) ? 2 : 0; c+= (pattern0[i] & 0x10) ? 1 : 0; PIX[i+8*x][4+y*8] = palette[c]; c = (pattern1[i] & 0x08) ? 2 : 0; c+= (pattern0[i] & 0x08) ? 1 : 0; PIX[i+8*x][3+y*8] = palette[c]; c = (pattern1[i] & 0x04) ? 2 : 0; c+= (pattern0[i] & 0x04) ? 1 : 0; PIX[i+8*x][2+y*8] = palette[c]; c = (pattern1[i] & 0x02) ? 2 : 0; c+= (pattern0[i] & 0x02) ? 1 : 0; PIX[i+8*x][1+y*8] = palette[c]; c = (pattern1[i] & 0x01) ? 2 : 0; c+= (pattern0[i] & 0x01) ? 1 : 0; PIX[i+8*x][0+y*8] = palette[c]; } } void create_pixel_map(char PIX[16][16], char* pattern0, char* pattern1,char* pattern2, char* pattern3, char* pattern4, char* pattern5,char* pattern6, char* pattern7) { create_pixel_section(PIX,0,0,pattern0,pattern1); create_pixel_section(PIX,1,0,pattern2,pattern3); create_pixel_section(PIX,0,1,pattern4,pattern5); create_pixel_section(PIX,1,1,pattern6,pattern7); } void create_pixel_map_flip(char PIX[16][16],char* pattern0, char* pattern1,char* pattern2, char* pattern3, char* pattern4, char* pattern5,char* pattern6, char* pattern7) { create_pixel_section_flip(PIX,0,0,pattern0,pattern1); create_pixel_section_flip(PIX,1,0,pattern2,pattern3); create_pixel_section_flip(PIX,0,1,pattern4,pattern5); create_pixel_section_flip(PIX,1,1,pattern6,pattern7); } void initialize(){ //Define Output and LEDs as outputs, and Switches as inputs OUT_DDR = 0xFF; DDRD = 0x00; DDRA = 0xFF; EICRA = 0x03; EIMSK = 0x01; // Initialize the UART uart_init(); stdout = &uart_str; // Setup all of the pixel maps create_pixel_map(STAND_R,s1_pattern0,s1_pattern1,s2_pattern0,s2_pattern1,s3_pattern0,s3_pattern1,s4_pattern0,s4_pattern1); create_pixel_map(RUN_1_R,r1_1_pattern0,r1_1_pattern1,r1_2_pattern0,r1_2_pattern1,r1_3_pattern0,r1_3_pattern1,r1_4_pattern0,r1_4_pattern1); create_pixel_map(RUN_2_R,r2_1_pattern0,r2_1_pattern1,r2_2_pattern0,r2_2_pattern1,r2_3_pattern0,r2_3_pattern1,r2_4_pattern0,r2_4_pattern1); create_pixel_map(RUN_3_R,r3_1_pattern0,r3_1_pattern1,r3_2_pattern0,r3_2_pattern1,r3_3_pattern0,r3_3_pattern1,r3_4_pattern0,r3_4_pattern1); create_pixel_map(TURN_R,t1_pattern0,t1_pattern1,t2_pattern0,t2_pattern1,t3_pattern0,t3_pattern1,t4_pattern0,t4_pattern1); create_pixel_map_flip(STAND_L,s1_pattern0,s1_pattern1,s2_pattern0,s2_pattern1,s3_pattern0,s3_pattern1,s4_pattern0,s4_pattern1); create_pixel_map_flip(RUN_1_L,r1_1_pattern0,r1_1_pattern1,r1_2_pattern0,r1_2_pattern1,r1_3_pattern0,r1_3_pattern1,r1_4_pattern0,r1_4_pattern1); create_pixel_map_flip(RUN_2_L,r2_1_pattern0,r2_1_pattern1,r2_2_pattern0,r2_2_pattern1,r2_3_pattern0,r2_3_pattern1,r2_4_pattern0,r2_4_pattern1); create_pixel_map_flip(RUN_3_L,r3_1_pattern0,r3_1_pattern1,r3_2_pattern0,r3_2_pattern1,r3_3_pattern0,r3_3_pattern1,r3_4_pattern0,r3_4_pattern1); create_pixel_map_flip(TURN_L,t1_pattern0,t1_pattern1,t2_pattern0,t2_pattern1,t3_pattern0,t3_pattern1,t4_pattern0,t4_pattern1); //Let this baby loose sei(); } void SPIInit() { // Initialize the UART // uart_init(); stdout = &uart_str; // _delay_us(100); // fprintf(stdout,"Starting SPI test: MASTER"); // make the MOS20I, SCK, and SS pins outputs DDRB |= (1< 2500){ // This is number of scanlines that have passes, meaning each count is ~63 us controller = txSPI(0x00); PORTA = controller; time=0; if(offset==5){ row = 1-row; offset = 0; }else if(++offset > 4) offset=1; if(~PIND & 0x40){ offset = 5; time = -2500; } // Alter the frame we are drawing picture = video[row][offset]; } } }