- /*
- * startup.c
- *
- */
- #define SIMULATOR
- //#define USBDM
- #include "box.xbm"
- #include "box_hit.xbm"
- #include "player.xbm"
- #include "wall.xbm"
- typedef unsigned int uint32_t;
- typedef unsigned short uint16_t;
- typedef unsigned char uint8_t;
- typedef struct {
- uint32_t moder;
- uint16_t otyper; // +0x4
- uint16_t otReserved;
- uint32_t ospeedr; // +0x8
- uint32_t pupdr; // +0xc
- uint8_t idrLow; // +0x10
- uint8_t idrHigh; // +0x11
- uint16_t idrReserved;
- uint8_t odrLow; // +0x14
- uint8_t odrHigh; // +0x15
- uint16_t odrReserved;
- } GPIO;
- typedef volatile GPIO* gpioPtr;
- #define GPIO_D (*((gpioPtr) 0x40020C00)) /* GPIO HIGH AND LOW Keypad */
- #define GPIO_E (*((gpioPtr) 0x40021000)) /* Graphic */
- #define SYS_TICK 0xE000E010
- #define STK_CTRL ((volatile unsigned int *) (SYS_TICK))
- #define STK_LOAD ((volatile unsigned int *) (SYS_TICK + 0x4))
- #define STK_VAL ((volatile unsigned int *) (SYS_TICK + 0x8))
- #define STK_CALIB ((volatile unsigned int *) (SYS_TICK + 0xC))
- /* MASKS FOR ASCII DISPLAY*/
- #define B_E 0x40 /* Enable-signal */
- #define B_SELECT 4 /* Select ASCII-display */
- #define B_RW 2 /* 0=Write, 1=Read */
- #define B_RS 1 /* 0=Control, 1=Data */
- /* MASKS FOR GRAPHIC DISPLAY */
- #define B_RST 0x20
- #define B_CS2 0x10
- #define B_CS1 0x08
- #define LCD_ON 0x3F
- #define LCD_OFF 0x3E
- #define LCD_DISP_START 0xC0
- #define LCD_SET_ADD 0x40
- #define LCD_SET_PAGE 0xB8
- #define LCD_BUSY 0x80
- typedef unsigned char uint8_t;
- /* TYPEDEFS FOR SPRITES */
- typedef struct tSpriteData{
- unsigned char width;
- unsigned char height;
- unsigned char* data;
- }SPRITEDATA, *PSPRITEDATA;
- typedef struct tSprite{
- char posx, posy;
- char dirx, diry;
- char speedx, speedy;
- } SPRITE, *PSPRITE;
- static void load_sprite(PSPRITEDATA s, unsigned char* data, int width, int height){
- s->width = width;
- s->height = height;
- s->data = data;
- }
- unsigned char ascii_read_status (void);
- void startup(void) __attribute__((naked)) __attribute__((section (".start_section")) );
- void startup ( void )
- {
- __asm volatile(
- " LDR R0,=0x2001C000\n" /* set stack */
- " MOV SP,R0\n"
- " BL main\n" /* call main */
- "_exit: B .\n" /* never return */
- ) ;
- }
- void delay_250ns(void){
- *STK_CTRL = 0;
- *STK_LOAD = ((168/4)-1); // One micro sec = 168 clock cycles -> 168/4 = 250 nano sec
- *STK_VAL = 0;
- *STK_CTRL = 0x5;
- while((*STK_CTRL & 0x10000) == 0){}
- *STK_CTRL = 0;
- }
- void delay_500ns(void){
- delay_250ns();
- delay_250ns();
- }
- void delay_micro(unsigned int us){
- #ifdef SIMULATOR
- us = us/1000;
- us++;
- #endif
- while(us > 0){
- delay_250ns();
- delay_250ns();
- delay_250ns();
- delay_250ns();
- us--;
- }
- }
- void delay_milli(unsigned int ms){
- #ifdef SIMULATOR
- ms = ms/1000;
- ms++;
- #endif
- while(ms > 0){
- delay_micro(1000);
- ms--;
- }
- }
- void init_app (void){
- GPIO_E.moder = 0x55555555;
- GPIO_D.moder = 0x55000000;
- }
- void graphic_ctrl_bit_set(uint8_t x){
- unsigned char c;
- c = GPIO_E.odrLow;
- c |= x;
- GPIO_E.odrLow = c;
- }
- void graphic_ctrl_bit_clear(uint8_t x){
- unsigned char c;
- c = GPIO_E.odrLow;
- c &= ~x;
- GPIO_E.odrLow = c;
- }
- void select_controller(uint8_t controller)
- {
- switch(controller)
- {
- case 0:
- graphic_ctrl_bit_clear(B_CS1|B_CS2);
- break;
- case B_CS1 :
- graphic_ctrl_bit_set(B_CS1);
- graphic_ctrl_bit_clear(B_CS2);
- break;
- case B_CS2 :
- graphic_ctrl_bit_set(B_CS2);
- graphic_ctrl_bit_clear(B_CS1);
- break;
- case B_CS1|B_CS2 :
- graphic_ctrl_bit_set(B_CS1|B_CS2);
- break;
- }
- }
- void graphic_wait_ready(void){
- graphic_ctrl_bit_clear(B_E);
- GPIO_E.moder = 0x00005555;
- graphic_ctrl_bit_clear(B_RS);
- graphic_ctrl_bit_set(B_RW);
- delay_500ns();
- while(GPIO_E.odrLow & 0x1){
- graphic_ctrl_bit_set(B_E);
- delay_500ns();
- graphic_ctrl_bit_clear(B_E);
- delay_500ns();
- }
- graphic_ctrl_bit_set(B_E);
- GPIO_E.moder = 0x55555555;
- }
- unsigned char graphic_read(uint8_t controller){
- uint8_t c;
- graphic_ctrl_bit_clear(B_E);
- GPIO_E.moder = 0x00005555;
- graphic_ctrl_bit_set(B_RS | B_RW);
- select_controller(controller);
- delay_500ns();
- graphic_ctrl_bit_set(B_E);
- delay_500ns();
- c = GPIO_E.idrHigh; //unsure if this is correct, but it should be (data in the higher bits?)
- graphic_ctrl_bit_clear(B_E);
- GPIO_E.moder = 0x55555555;
- if(controller == B_CS1){
- select_controller(B_CS1);
- graphic_wait_ready();
- }
- if(controller == B_CS2){
- select_controller(B_CS2);
- graphic_wait_ready();
- }
- return c; // Hmm?
- }
- static void graphic_write(uint8_t value, uint8_t controller)
- {
- GPIO_E.odrHigh = value;
- select_controller(controller);
- delay_500ns();
- graphic_ctrl_bit_set(B_E);
- delay_500ns();
- graphic_ctrl_bit_clear(B_E);
- if (controller == B_CS1)
- {
- select_controller(B_CS1);
- graphic_wait_ready();
- }
- else if (controller == B_CS2)
- {
- select_controller(B_CS2);
- graphic_wait_ready();
- }
- GPIO_E.odrHigh = 0;
- graphic_ctrl_bit_set(B_E);
- select_controller(0);
- }
- void graphic_write_command(uint8_t cmd, uint8_t controller){
- graphic_ctrl_bit_clear(B_E);
- select_controller(controller);
- graphic_ctrl_bit_clear(B_RS);
- graphic_ctrl_bit_clear(B_RW);
- graphic_write(cmd, controller);
- }
- void graphic_write_data(uint8_t data, uint8_t controller){
- graphic_ctrl_bit_clear(B_E);
- select_controller(controller);
- graphic_ctrl_bit_set(B_RS);
- graphic_ctrl_bit_clear(B_RW);
- graphic_write(data, controller);
- }
- uint8_t graphic_read_data(unsigned char controller){
- (void) graphic_read(controller); /* returns bullshit */
- return graphic_read(controller); /* returns correct data */
- }
- void graphic_initialize(void){
- graphic_ctrl_bit_set(B_E);
- delay_micro(10);
- graphic_ctrl_bit_clear(B_CS1 | B_CS2 | B_RST | B_E);
- delay_milli(30);
- graphic_ctrl_bit_set(B_RST);
- graphic_write_command(LCD_OFF, B_CS1 | B_CS2);
- graphic_write_command(LCD_ON, B_CS1 | B_CS2);
- graphic_write_command(LCD_DISP_START, B_CS1 | B_CS2);
- graphic_write_command(LCD_SET_ADD, B_CS1 | B_CS2);
- graphic_write_command(LCD_SET_PAGE, B_CS1 | B_CS2);
- select_controller(0);
- }
- void graphic_clear_screen(void){
- for(int page = 0; page <= 7; page++){
- graphic_write_command(LCD_SET_PAGE | page, B_CS1 | B_CS2);
- graphic_write_command(LCD_SET_ADD | 0, B_CS1 | B_CS2);
- for(int add = 0; add <= 63; add++){
- graphic_write_data(0, B_CS1 | B_CS2);
- }
- }
- }
- void graphic_clear_lower(void){
- for(int page = 0; page <= 7; page++){
- graphic_write_command(LCD_SET_PAGE | page, B_CS1 | B_CS2);
- graphic_write_command(LCD_SET_ADD | 0, B_CS1 | B_CS2);
- for(int add = 0; add <= 63; add++){
- graphic_write_data(0, B_CS1 | B_CS2);
- }
- }
- }
- void pixel(int x, int y, int set) {
- uint8_t mask, c, controller;
- int index;
- if((x < 0) || (y < 0) || (x > 128) || (y > 64)) return;
- index = (y-1)/8;
- switch( (y-1)%8 ) {
- case 0: mask = 1; break;
- case 1: mask = 2; break;
- case 2: mask = 4; break;
- case 3: mask = 8; break;
- case 4: mask = 0x10; break;
- case 5: mask = 0x20; break;
- case 6: mask = 0x40; break;
- case 7: mask = 0x80; break;
- }
- if(set == 0)
- mask = ~mask;
- if(x > 64){
- controller = B_CS2;
- x = x - 65;
- } else {
- controller = B_CS1;
- x = x-1;
- }
- graphic_write_command(LCD_SET_ADD | x, controller );
- graphic_write_command(LCD_SET_PAGE | index, controller );
- c = graphic_read_data(controller);
- graphic_write_command(LCD_SET_ADD | x, controller);
- if(set)
- mask = mask | c;
- else
- mask = mask & c;
- graphic_write_data(mask, controller);
- }
- //void pixel_buffer(int x, int y) {
- // uint8_t mask;
- // int index = 0;
- // if( (x > 128 ) || (x < 0) || (y > 64) || (y < 0) ) return;
- //
- // mask = 1 << ((y-1)%8);
- //
- // if(x > 64) {
- // x -= 65;
- // index = 512;
- // }
- //
- // index += x + ((y-1)/8)*64;
- // backBuffer[index] |= mask;
- //}
- //
- //
- //void graphic_draw_screen(void) {
- // uint8_t i, j, controller, c;
- // unsigned int k = 0;
- // for(c = 0; c <= 1; c++){
- // controller = (c == 0) ? B_CS1 : B_CS2;
- // for(j = 0; j < 8; j++){
- // graphic_write_command(LCD_SET_PAGE | j, controller);
- // graphic_write_command(LCD_SET_ADD | 0, controller);
- // for(i = 0; i < 64; i++, k++){
- // graphic_write_data(backBuffer[k], controller);
- // }
- // }
- // }
- //}
- /*----------------------- ASCII -----------------------*/
- /* Addressera ASCII-display och ettställ de bitar som är 1 i x */
- void ascii_ctrl_bit_set(unsigned char x){
- unsigned char c;
- c = GPIO_E.odrLow;
- c |= (B_SELECT | x);
- GPIO_E.odrLow = c;
- }
- void ascii_ctrl_bit_clear(unsigned char x){
- unsigned char c;
- c = GPIO_E.odrLow;
- c &= (B_SELECT | ~x);
- GPIO_E.odrLow = c;
- }
- void ascii_write_controller(unsigned char c){
- ascii_ctrl_bit_set(B_E);
- GPIO_E.odrHigh = c;
- delay_250ns();
- ascii_ctrl_bit_clear(B_E);
- }
- unsigned char ascii_read_controller(void){
- ascii_ctrl_bit_set(B_E);
- delay_250ns();
- delay_250ns();
- unsigned char c = GPIO_E.idrHigh;
- ascii_ctrl_bit_clear(B_E);
- return c;
- }
- void ascii_write_cmd(unsigned char command){
- ascii_ctrl_bit_clear(B_RS | B_RW);
- ascii_write_controller(command);
- }
- void ascii_write_data(unsigned char data){
- ascii_ctrl_bit_set(B_RS);
- ascii_ctrl_bit_clear(B_RW);
- ascii_write_controller(data);
- }
- void ascii_write_char(unsigned char c){
- while((ascii_read_status() & 0x80) == 0x80){}
- delay_micro(8);
- ascii_write_data(c);
- delay_micro(45);
- }
- unsigned char ascii_read_status(void){
- unsigned char c;
- GPIO_E.moder = 0x00005555;
- ascii_ctrl_bit_clear(B_RS);
- ascii_ctrl_bit_set(B_RW);
- c = ascii_read_controller();
- GPIO_E.moder = 0x55555555;
- return c;
- }
- unsigned char ascii_read_data(void){
- GPIO_E.moder = 0x00005555;
- ascii_ctrl_bit_set(B_RS);
- ascii_ctrl_bit_set(B_RW);
- unsigned char c = ascii_read_controller();
- GPIO_E.moder = 0x55555555;
- return c;
- }
- void ascii_init(void){
- while((ascii_read_status() & 0x80) == 0x80){}
- delay_micro(8);
- ascii_write_cmd(0x38); // Rows: 2, Size: 5x8
- delay_micro(40);
- ascii_write_cmd(0x0E); // Display: on, Cursor: constant on
- delay_micro(40);
- ascii_write_cmd(0x06); // Increment, Shift: off
- delay_micro(40);
- }
- void ascii_command (unsigned char command)
- {
- while(ascii_read_status() & 0x80 == 0x80){}
- delay_micro(8); /* Latenstid för kommando */
- ascii_write_cmd(command); /* Kommandot som ska exekveras; t.ex. 1 - Clear Display */
- delay_micro(40); /* Avrundat uppåt; istället för 1,53ms */
- }
- void ascii_gotoxy(int x, int y){
- unsigned char adress;
- if(y != 1)
- {
- adress = 0x40|(x - 1);
- }
- else
- {
- adress = x - 1;
- }
- ascii_write_cmd(0x80|adress);
- delay_micro(45);
- }
- /*--------------------------- ASCII END ------------------------------*/
- /*--------------------------- KEYPAD -----------------------------*/
- //void activateRow(unsigned int row){
- // switch(row){
- // case 1: GPIO_D.odrHigh = 0x10; break;
- // case 2: GPIO_D.odrHigh = 0x20; break;
- // case 3: GPIO_D.odrHigh = 0x40; break;
- // case 4: GPIO_D.odrHigh = 0x80; break;
- // case 0: GPIO_D.odrHigh = 0x00; break;
- // }
- //}
- //unsigned char keyb(void){
- // int row, column;
- // unsigned char key[]={1,2,3,0xA,4,5,6,0xB,7,8,9,0xC,0xE,0,0xF,0xD};
- //
- // for(row = 1; row <= 4; row++){
- // activateRow(row);
- // column = readColumn();
- //
- // if(column){
- // activateRow(0);
- // return key[4*(row - 1) + column - 1];
- // }
- // }
- // activateRow(0);
- // return 0xFF;
- //}
- /*--------------------------- KEYPAD END-----------------------------*/
- void draw_sprite(PSPRITEDATA sd, PSPRITE s, char set){
- int i,j,k, width_in_bytes;
- if (sd->width % 8 == 0)
- width_in_bytes = (sd->width / 8);
- else
- width_in_bytes = (sd->width / 8 + 1);
- for(i = 0; i < sd->height; i++){
- for (j = 0; j < width_in_bytes; j++){
- unsigned char byte = sd->data[i * width_in_bytes + j];
- for (k = 0; k < 8; k++){
- if (byte & (1 << k))
- pixel(8 * j + k + s->posx + 1, i + s->posy + 1, set);
- }
- }
- }
- }
- void sprite_move(PSPRITE s, uint8_t player){
- char newPos = s->dirx*s->speedx + s->posx;
- if(player == 1){
- if(newPos > 2 && newPos < 45)
- s->posx = newPos;
- }else if(player == 2){
- if(newPos < 69 && newPos > 128)
- s->posx = newPos;
- }
- //s->posy += s->speedy*s->diry;
- }
- SPRITE box[40];
- SPRITE player1 = {
- 5,60,
- 0,0,
- 2,2
- };
- SPRITE player2 = {
- 90,60,
- 0,0,
- 2,2
- };
- PSPRITE p1 = &player1;
- PSPRITE p2 = &player2;
- int readColumn(){
- unsigned char c;
- unsigned int r;
- r = 0;
- c = GPIO_D.idrHigh;
- if(c & 0x1)
- r += 1;
- if(c & 0x2)
- r += 10;
- if(c & 0x4)
- r += 100;
- if(c & 0x8)
- r += 1000;
- return r;
- }
- unsigned char keyb(void){
- int r = 0;
- GPIO_D.odrHigh = 0x10; // AKTIVERA RAD 1
- r = readColumn();
- switch(r){
- case 1: p1->dirx = -1; break;
- case 10: p1->dirx = 1; break;
- case 100: p2->dirx = -1; break;
- case 1000: p2->dirx = 1; break;
- case 101: p1->dirx = -1; p2->dirx = -1; break;
- case 1001: p1->dirx = -1; p2->dirx = 1; break;
- case 110: p1->dirx = 1; p2->dirx = -1; break;
- case 1010: p1->dirx = 1; p2->dirx = 1; break;
- default: p2->dirx = 0; p1->dirx = 0;
- }
- GPIO_D.odrHigh = 0x00;
- return 0;
- }
- void main(void){
- char c;
- int i, j, k;
- k = 0;
- for(i = 0; i < 5; i++){
- for(j = 0; j < 4; j++){
- box[k].posx = i * 11 + 2;
- box[k].posy = j * 4;
- k++;
- }
- }
- for(i = 0; i < 5; i++){
- for(j = 0; j < 4; j++){
- box[k].posx = i * 11 + 70;
- box[k].posy = j * 4;
- k++;
- }
- }
- init_app();
- graphic_initialize();
- ascii_init();
- #ifndef SIMULATOR
- graphic_clear_screen();
- #endif
- ascii_ctrl_bit_set(2);
- ascii_gotoxy(1, 1);
- char *s;
- char test1[] = "Break Out!";
- char test2[] = "0-Player 1 | Player 2-0";
- s = test1;
- while(*s)
- ascii_write_char(*s++);
- ascii_gotoxy(1, 2);
- s = test2;
- while(*s)
- ascii_write_char(*s++);
- pixel(10, 10, 1);
- load_sprite("box.xbm", box_bits, box_width, box_height);
- load_sprite("box_hit.xbm", box_hit_bits, box_hit_width, box_hit_height);
- load_sprite("player.xbm", player_bits, player_width, player_height);
- load_sprite("wall.xbm", wall_bits, wall_width, wall_height);
- #ifndef SIMULATOR
- /* WRITE BORDERS */
- for(i = 0; i < 64; i++){
- pixel(1, i, 1);
- pixel(60, i, 1);
- pixel(69, i, 1);
- pixel(128, i, 1);
- }
- #endif
- int count;
- while(1){
- /* CLEAR THEN WRITE */
- #ifndef SIMULATOR
- count++;
- if(count % 4){
- for(i = 0; i < 40; i++){
- draw_sprite("box.xbm", &box[i], 0);
- draw_sprite("box.xbm", &box[i], 1);
- }
- }
- #endif
- draw_sprite("player.xbm", p1, 0);
- draw_sprite("player.xbm", p2, 0);
- keyb(); /* Read keypad */
- sprite_move(p1, 1);
- sprite_move(p2, 2);
- draw_sprite("player.xbm", p1, 1);
- draw_sprite("player.xbm", p2, 1);
- //delay_milli(20);
- }
- return;
- }