// source code for the mega128. This processor will write to the memory array // and perform calculations that will change the contents of the array // Lines are 256 pixels long #include #define maxSprites 4 // assembly I/O definitions #asm ;**** I/O Register Definitions ($3F-$00) **** .equ PORTA = $1B .equ DDRA = $1A .equ PINA = $19 .equ PORTB = $18 .equ DDRB = $17 .equ PINB = $16 .equ PORTC = $15 .equ DDRC = $14 ; New .equ PINC = $13 ; New .equ PORTD = $12 .equ DDRD = $11 .equ PIND = $10 .equ PORTE = $03 .equ DDRE = $02 .equ PINE = $01 .equ PINF = $00 #endasm // PORTA, ADDRESS LOW BYTE #define ADDLOW PORTA #define MEM_LOW_OE DDRA // PORTC, ADDRESS HIGH BYTE + DATA #define ADDHIGH PORTC #define MEM_HIGH_OE DDRC // PORTD, MEMORY OUTPUT #define MEM_OUTPUT PORTD #define MEM_OUTPUT_OE DDRD // PORTE.1 write enable #define MEM_WE PORTE.1 // MEMORY WE, high for reads, low for writes // PORTG, PING.0 used for activating display // State Machines // Memory Access unsigned char memAccessState, memUpdateState; #define start 0 #define stop 1 #define erase1 0 #define draw 1 #define erase2 2 #define erase3 3 #define erase4 4 // screen array changes unsigned char programState; #define screenInitialize 0 #define screenMaintain 1 #define screenRedraw 2 // Global Variables unsigned char textureGrid[32][16]; // Stores the texture located in the area unsigned char ranFlag,memFlag; // says if the program or memory code has been run already // functions void memWrite(int address, unsigned char output); // write a pixel in external memory void textWrite(int address, unsigned char textNum); // write a texture to external memory void sprWrite(int address, unsigned char sprNum); // write a sprite to external memory void combineSprText(unsigned int address, unsigned char sprNum, unsigned char textNum); // write a sprite/texture combination to memory #define open 0 #define closed 1 unsigned char spriteStatus, spriteTime; // done this way so more variables could be added later, as I'm sure there // are more that could be added, I just didn't need to for the tech demo struct sprite_variables { int address; } sprite_var[maxSprites]; // put textures here, 8 bytes by 8 bytes, each texture is offset by 64, meaning // texture 0 starts at 0, texture 1 starts at 64, texture 2 starts at 128, etc. flash unsigned char textures[1000]={ // 8x8 textures // green 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38, 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38, 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38, 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38, 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38, 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38, 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38, 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38, // blue 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, // red 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, //some color 0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7, 0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7, 0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7, 0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7, 0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7, 0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7, 0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7, 0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7, // some other color 0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, 0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, 0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, 0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, 0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, 0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, 0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, 0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, // left smiley eye 0xC0,0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0, 0xC0,0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0, 0xC0,0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0, 0xC0,0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0, 0xC0,0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0, 0xC0,0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0, 0xC0,0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0, 0xC0,0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0, // right smiley eye 0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0,0xC0, 0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0,0xC0, 0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0,0xC0, 0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0,0xC0, 0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0,0xC0, 0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0,0xC0, 0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0,0xC0, 0xC0,0xC0,0x07,0x07,0x07,0xC0,0xC0,0xC0, // left smiley smile 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0x07,0x07,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0x07,0x07,0x07,0xC0,0xC0,0xC0,0xC0,0xC0, 0xC0,0x07,0x07,0x07,0xC0,0xC0,0xC0,0xC0, 0xC0,0xC0,0x07,0x07,0x07,0x07,0x07,0x07, 0xC0,0xC0,0xC0,0x07,0x07,0x07,0x07,0x07, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, // right smiley smile 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x07, 0xC0,0xC0,0xC0,0xC0,0xC0,0x07,0x07,0x07, 0xC0,0xC0,0xC0,0xC0,0x07,0x07,0x07,0xC0, 0x07,0x07,0x07,0x07,0x07,0x07,0xC0,0xC0, 0x07,0x07,0x07,0x07,0x07,0xC0,0xC0,0xC0, 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0}; // put sprites here, 8 bytes by 8 bytes, each sprite is offset by 64, meaning // sprite 0 starts at 0, sprite 1 starts at 64, sprite 2 starts at 128, etc. flash unsigned char sprites[512]={ // 8x8 sprites 0x01 indicates transparent area /* Starter 8x8 Block 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, */ //OPEN // upper left 0x01,0x01,0x01,0x01,0x3F,0x3F,0x3F,0x3F, 0x01,0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, // upper right 0x3F,0x3F,0x3F,0x3F,0x01,0x01,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x01,0x01,0x01,0x01, 0x3F,0x3F,0x3F,0x01,0x01,0x01,0x01,0x01, 0x3F,0x3F,0x01,0x01,0x01,0x01,0x01,0x01, 0x3F,0x01,0x01,0x01,0x01,0x01,0x01,0x01, // lower left 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x01,0x01,0x01,0x3F,0x3F,0x3F,0x3F, // lower right 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x3F,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x3F,0x3F,0x01,0x01,0x01,0x01,0x01,0x01, 0x3F,0x3F,0x3F,0x01,0x01,0x01,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x01,0x01,0x01,0x01, //CLOSED // upper left 4 0x01,0x01,0x01,0x01,0x3F,0x3F,0x3F,0x3F, 0x01,0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, // upper right 0x3F,0x3F,0x3F,0x3F,0x01,0x01,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, // lower left 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x01,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x01,0x01,0x01,0x01,0x3F,0x3F,0x3F,0x3F, // lower right 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x01,0x01, 0x3F,0x3F,0x3F,0x3F,0x01,0x01,0x01,0x01}; void textWrite(int address, unsigned char textNum) { int textLocation; unsigned char i,j; int currentAddress; currentAddress = address; textLocation = (int)textNum*64; for (j=0;j<8;j++) { for (i=0;i<8;i++) { memWrite(currentAddress + i, textures[textLocation + i]); } currentAddress = currentAddress + 256; textLocation = textLocation + 8; } } void sprWrite(int address, unsigned char sprNum) { int sprLocation; unsigned char i, j; int currentAddress; currentAddress = address; sprLocation = (int)sprNum*64; for (j=0;j<8;j++) { for (i=0;i<8;i++) { if (sprites[sprLocation+i] != 0x01) memWrite(currentAddress + i, sprites[sprLocation + i]); } currentAddress = currentAddress + 256; sprLocation = sprLocation + 8; } } // At 25 cycles per pixel write, it would take 84ms to write the entire screen array // This is with hardcoded writes, however. If I have to figure out where to write, that will take // more time. Solution: Figure out where stuff goes during downtime. Store this, then // use these numbers to write directly void memWrite(int address, unsigned char output) { #asm ;address -> Y+1 ;output -> Y+0 ;// Place low address ;ADDLOW = address; ;// Place high address ;ADDHIGH = (address >> 8); LDD R30,Y+1 LDD R31,Y+2 OUT PORTA,R30 OUT PORTC,R31 ;// load data ;DATAOUT = output; LD R30,Y OUT PORTD,R30 ;// write data ;MEM_WE = 0; CBI 0x3,1 ;// go back to read mode ;MEM_WE = 1; SBI 0x3,1 #endasm } void initialize(void) { // Port Initialization // PORTG as output DDRG = 0b11111; PORTG = 0x00; // Ports initialize in high impedence state on start up // Turn on select PORTS, which will always be output DDRE = 0b00000010; PORTE = 0b00000010; // PINF.1 input, change memory on high DDRF = 0x00; // Initialize Timers // Initialize State Variables memAccessState = stop; // Initialize External Interrupts // Enable external interrupt 0 EICRA = 0b00000010; EIFR = 0b00000001; } void programCode(void) { unsigned char i; int temp; ranFlag = 1; memFlag = 0; // figure out the color that has to be rewritten writeOverColor = textureGrid[sprite_var[0].address/8][16]; // Sprites for (i=0;i=0 && j<3) textureGrid[i][j] = 0; if (j>=3 && j <6) textureGrid[i][j] = 1; if (j>=6 && j <9) textureGrid[i][j] = 2; if (j>=9 && j <12) textureGrid[i][j] = 3; if (j>=12 && j<16) textureGrid[i][j] = 4; } } // END OF TEXTURE GRID INITIALIZATION // Write textureGrid to external memory for(j=0;j<16;j++) { for(i=0;i<32;i++) { address = (int)(j*2048); textWrite(address + i*8,textureGrid[i][j]); } } // Initialize Sprite PACMAN sprite_var[0].address = 0x3300; sprite_var[1].address = 0x3308; sprite_var[2].address = 0x3A00; sprite_var[3].address = 0x3A08; sprWrite(sprite_var[0].address,0); sprWrite(sprite_var[1].address,1); sprWrite(sprite_var[2].address,2); sprWrite(sprite_var[3].address,3); } void main(void) { initialize(); while(1) { switch (programState) { case screenInitialize: // Activate memory and latch ports DDRA = 0xFF; DDRC = 0xFF; DDRD = 0xFF; // write the initial screen initialScreen(); DDRA = 0x00; PORTA = 0x00; DDRC = 0x00; PORTD = 0x00; DDRD = 0x00; PORTD = 0x00; // tell mega16 that it can write to screen now PORTG = 0b00001; // switch program state to screen maintainance programState = screenMaintain; break; case screenMaintain: switch (memAccessState) { case start: if (memFlag == 0) memoryUpdate(); break; case stop: if (ranFlag == 0) programCode(); break; } break; case screenRedraw: break; } if (PINF.0 == 1) { memAccessState = start; } else { memAccessState = stop; } } }