diff --git a/firmware/l0dable/EXPORTS b/firmware/l0dable/EXPORTS index d4936d2..66917af 100644 --- a/firmware/l0dable/EXPORTS +++ b/firmware/l0dable/EXPORTS @@ -91,6 +91,7 @@ GetVoltage isNight _timectr crc16 +randomInit getRandom getSeconds iapReadSerialNumber diff --git a/firmware/l0dable/blink.c b/firmware/l0dable/blink.c index 06ae4e7..5e69dba 100644 --- a/firmware/l0dable/blink.c +++ b/firmware/l0dable/blink.c @@ -5,8 +5,11 @@ #include "usetable.h" void ram(void){ + char x = gpioGetValue(RB_LED1); + for (int x=0;x<20;x++){ gpioSetValue (RB_LED1, x%2); delayms(50); }; + gpioSetValue (RB_LED1, x); }; diff --git a/firmware/l0dable/jump.c b/firmware/l0dable/jump.c new file mode 100644 index 0000000..a83d940 --- /dev/null +++ b/firmware/l0dable/jump.c @@ -0,0 +1,388 @@ +/** + * r0ket JUMP! + * + * Author: webholics + */ + +#include +#include +#include "basic/basic.h" +#include "basic/config.h" +#include "basic/random.h" +#include "lcd/render.h" +#include "lcd/display.h" +#include "funk/mesh.h" +#include "usetable.h" + +#define PLAYER_SPRITE_WIDTH 9 +#define PLAYER_SPRITE_HEIGHT 10 +static const bool PLAYER_SPRITE_DOWN[] = { + 0,0,0,1,1,1,0,0,0, + 1,0,0,1,1,1,0,0,1, + 1,1,0,0,1,0,0,1,1, + 0,1,1,1,1,1,1,1,0, + 0,0,1,1,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0, + 0,0,0,1,1,1,0,0,0, + 0,0,1,1,0,1,1,0,0, + 0,0,1,1,0,1,1,0,0, + 0,0,1,1,0,1,1,0,0 +}; +static const bool PLAYER_SPRITE_UP[] = { + 0,0,0,1,1,1,0,0,0, + 0,0,0,1,1,1,0,0,0, + 0,0,0,0,1,0,0,0,0, + 0,0,1,1,1,1,1,0,0, + 0,1,1,1,1,1,1,1,0, + 1,1,0,1,1,1,0,1,1, + 0,0,0,1,1,1,0,0,0, + 0,0,1,1,0,1,1,0,0, + 0,0,1,1,0,1,1,0,0, + 0,0,1,1,0,1,1,0,0 +}; + +#define GRAVITY 1 +#define JUMP_FORCE -9 +#define MAX_VEL_Y 5 +#define MAX_VEL_X 2 + +#define NUM_PLATFORMS 30 +#define PLATFORM_MARGIN_Y 14 +#define PLATFORM_HEIGHT 3 +#define PLATFORM_WIDTH 20 +#define SPEEDUP_EVERY_FPS 1000 +#define REDUCE_PLATFORM_EVERY_FPS 500 + +#define POS_PLAYER_Y RESY-PLATFORM_HEIGHT +#define POS_PLAYER_X (RESX+PLAYER_SPRITE_WIDTH)/2 + +struct gamestate { + bool running; + + char player_x; + int player_y; + int player_y_vel; + int player_x_vel; + bool player_ground; + char scroll_speed; + uint32_t scroll_pos; + + char platform_width; + int platform_index; + int platforms_y[NUM_PLATFORMS]; + char platforms_x1[NUM_PLATFORMS]; + char platforms_x2[NUM_PLATFORMS]; +} game; + +static void splash_scene(); +static void init_game(); +static void draw_player(); +static void move_player(long frame_count); +static void update_platforms(long frame_count); +static void draw_platforms(); +static void draw_hud(); +static bool gameover_scene(); +static void blink_led(); +static bool highscore_set(uint32_t score, char nick[]); +static uint32_t highscore_get(char nick[]); + +void ram(void) { + + splash_scene(); + + long frame_count = 0; + init_game(); + + while(1) { + frame_count++; + + lcdFill(0); + update_platforms(frame_count); + move_player(frame_count); + draw_platforms(); + draw_player(); + draw_hud(); + blink_led(); + lcdDisplay(); + + if(!game.running) { + if(!gameover_scene()){ + delayms_queue_plus(10,1); + return; + } + init_game(); + } + delayms_queue_plus(24,0); + } +} + +static void splash_scene() { + uint32_t highscore; + char highnick[20]; + + char key = 0; + while(key == 0) { + getInputWaitRelease(); + + int dy = getFontHeight(); + int s1x = DoString(0, 0, "r0ket"); + s1x = (RESX-s1x)/2; + int s2x = DoString(0, 0, "JUMP!"); + s2x = (RESX-s2x)/2; + + lcdFill(0); + + DoString(s1x, 3*dy, "r0ket"); + DoString(s2x, 4*dy, "JUMP!"); + DoString(0, 7*dy, "by webholics"); + + highscore = highscore_get(highnick); + + int s3x = DoInt(0, 0, highscore); + DoChar(s3x, 0, 'm'); + DoString (0, dy, highnick); + + lcdDisplay(); + + key = getInputWaitTimeout(1000); + } +} + +static void init_game() { + game.running = true; + + game.player_x = POS_PLAYER_X; + game.player_y = POS_PLAYER_Y; + game.player_y_vel = 0; + game.player_x_vel = 0; + game.player_ground = true; + game.scroll_speed = 8; + game.platform_width = 20; + game.scroll_pos = 0; + + game.platform_index = 0; + game.platforms_y[0] = RESY - PLATFORM_HEIGHT; + game.platforms_x1[0] = 0; + game.platforms_x2[0] = RESX; + for(int i = 1; i < NUM_PLATFORMS; i++) { + game.platforms_y[i] = RESY+1; + } +} + +static void update_platforms(long frame_count) { + // create new platforms + while(1) { + int y = game.platforms_y[game.platform_index]; + if(y <= 0) { + break; + } + y -= PLATFORM_MARGIN_Y; + int x = getRandom() % (RESX-game.platform_width); + game.platform_index = (game.platform_index+1)%NUM_PLATFORMS; + game.platforms_y[game.platform_index] = y; + game.platforms_x1[game.platform_index] = x; + game.platforms_x2[game.platform_index] = x + game.platform_width-1; + } + + if(game.scroll_speed > 1 && frame_count % SPEEDUP_EVERY_FPS == 0) { + game.scroll_speed--; + } + if(game.platform_width > 5 && frame_count % REDUCE_PLATFORM_EVERY_FPS == 0) { + game.platform_width--; + } + + // move platforms + int scroll_speed = game.scroll_speed; + if(game.player_y-PLAYER_SPRITE_HEIGHT < 0) { + scroll_speed += (game.player_y-PLAYER_SPRITE_HEIGHT) / 5 - 1; + if(scroll_speed <= 0) + scroll_speed = 1; + } + if(frame_count % scroll_speed == 0) { + game.scroll_pos++; + for(int i = 0; i < NUM_PLATFORMS; i++) { + game.platforms_y[i]++; + } + } +} + +static void draw_platforms() { + for(int i = 0; i < NUM_PLATFORMS; i++) { + if(game.platforms_y[i] <= RESY) { + for(int x = game.platforms_x1[i]; x <= game.platforms_x2[i]; x++) { + for(int y = game.platforms_y[i]; y < game.platforms_y[i]+PLATFORM_HEIGHT; y++) { + if(y >= 0 && y <= RESY) { + lcdSetPixel(x, y, 1); + } + } + } + } + } +} + +static void draw_player() { + bool* sprite; + if(game.player_y_vel > 0) { + sprite = PLAYER_SPRITE_DOWN; + } + else { + sprite = PLAYER_SPRITE_UP; + } + for(int x = 0; x < PLAYER_SPRITE_WIDTH; x++) { + for(int y = 0; y < PLAYER_SPRITE_HEIGHT; y++) { + int py = game.player_y + y - PLAYER_SPRITE_HEIGHT; + if(sprite[x + y*PLAYER_SPRITE_WIDTH] && py >= 0 && py < RESY) { + lcdSetPixel( + (game.player_x + x)%RESX, + py, + 1); + } + } + } + + if(game.player_y < 0) { + int player_x_center = game.player_x + PLAYER_SPRITE_WIDTH/2; + for(int y = 0; y < 2; y++) { + for(int x = player_x_center-2; x <= player_x_center+2; x++) { + if(x >= 0 && x < RESX && y >= 0 && y < RESY) { + lcdSetPixel(x, y, 1); + } + } + } + } +} + +static void move_player(long frame_count) { + // move x + if(gpioGetValue(RB_BTN0) == 0) { + game.player_x_vel--; + } + else if(gpioGetValue(RB_BTN1) == 0) { + game.player_x_vel++; + } + else { + game.player_x_vel = 0; + } + if(game.player_x_vel > MAX_VEL_X) { + game.player_x_vel = MAX_VEL_X; + } + else if(game.player_x_vel < -1*MAX_VEL_X) { + game.player_x_vel = -1*MAX_VEL_X; + } + game.player_x += game.player_x_vel + RESX; + game.player_x %= RESX; + + // move y (jump) + // half the speed + if(frame_count%2 == 0) { + + int old_y = game.player_y; + + if(game.player_ground) { + game.player_y_vel = JUMP_FORCE; + game.player_ground = false; + } + + game.player_y_vel += GRAVITY; + game.player_y_vel = game.player_y_vel > MAX_VEL_Y ? MAX_VEL_Y : game.player_y_vel; + int new_y = old_y + game.player_y_vel; + + // collision detection + int player_x_center = game.player_x + PLAYER_SPRITE_WIDTH/2; + for(int i = 0; i < NUM_PLATFORMS; i++) { + if(game.player_y_vel > 0 + && old_y < game.platforms_y[i] + && new_y >= game.platforms_y[i] + && game.platforms_x1[i] <= player_x_center+2 + && game.platforms_x2[i] >= player_x_center-2) { + + game.player_y = game.platforms_y[i]-1; + game.player_y_vel = 0; + game.player_ground = true; + + break; + } + } + + game.player_y = new_y; + + if(game.player_y > RESY + PLAYER_SPRITE_HEIGHT) { + game.running = false; + } + } +} + +static void draw_hud() { + int x = DoInt(0, 0, game.scroll_pos / 15); + DoChar(x, 0, 'm'); +} + +static void blink_led() { + // this is r0ket booooost! + if(game.player_y < 0) { + gpioSetValue(RB_LED0, 1); + gpioSetValue(RB_LED1, 1); + gpioSetValue(RB_LED2, 1); + gpioSetValue(RB_LED3, 1); + return; + } + + gpioSetValue(RB_LED0, game.player_ground); + gpioSetValue(RB_LED1, game.player_ground); + gpioSetValue(RB_LED2, game.player_ground); + gpioSetValue(RB_LED3, game.player_ground); +} + +static bool gameover_scene() { + int dy = getFontHeight(); + int s1x = DoString(0, 0, "GAME OVER!"); + s1x = (RESX-s1x)/2; + int s2x = DoString(0, 0, "HIGHTSCORE!"); + s2x = (RESX-s2x)/2; + + char key = 0; + while(key != BTN_UP && key != BTN_DOWN) { + lcdClear(); + + if(highscore_set(game.scroll_pos / 15, GLOBAL(nickname))) + DoString (s2x, dy, "HIGHSCORE!"); + else + DoString(s1x, dy, "GAME OVER!"); + + int x = DoInt(0, 3*dy, game.scroll_pos / 15); + DoChar(x, 3*dy, 'm'); + + DoString(0, 5*dy, "UP to play"); + DoString(0, 6*dy, "DOWN to quit"); + + lcdDisplay(); + + key = getInputWaitTimeout(5000); + } + + return !(key==BTN_DOWN); +} + +// thank you space invaders ;) + +static bool highscore_set(uint32_t score, char nick[]) { + MPKT * mpkt= meshGetMessage('j'); + if(MO_TIME(mpkt->pkt)>score) + return false; + + MO_TIME_set(mpkt->pkt,score); + strcpy((char*)MO_BODY(mpkt->pkt),nick); + if(GLOBAL(privacy)==0){ + uint32touint8p(GetUUID32(),mpkt->pkt+26); + mpkt->pkt[25]=0; + }; + return true; +} + +static uint32_t highscore_get(char nick[]){ + MPKT * mpkt= meshGetMessage('j'); + + strcpy(nick,(char*)MO_BODY(mpkt->pkt)); + + return MO_TIME(mpkt->pkt); +} diff --git a/firmware/l0dable/r0type.c b/firmware/l0dable/r0type.c new file mode 100644 index 0000000..355e7e0 --- /dev/null +++ b/firmware/l0dable/r0type.c @@ -0,0 +1,485 @@ +/** + * r0type + * + * Author: @ranzwertig + * + */ + +#include +#include + +#include "basic/basic.h" +#include "basic/config.h" +#include "lcd/render.h" +#include "lcd/display.h" +#include "funk/mesh.h" +#include "usetable.h" + +#define SHIP_HEIGHT 9 +#define SHIP_WIDTH 12 +#define SHIP_ARRAY_SIZE 108 + +#define LIFE_WIDTH 11 +#define LIFE_HEIGHT 9 +#define LIFE_ARRAY_SIZE 99 + +#define ASTEROID_1_HEIGHT 6 +#define ASTEROID_1_WIDTH 6 +#define ASTEROID_1_ARRAY_SIZE 36 + +#define ASTEROID_3_HEIGHT 8 +#define ASTEROID_3_WIDTH 8 +#define ASTEROID_3_ARRAY_SIZE 64 + +#define ASTEROID_2_HEIGHT 7 +#define ASTEROID_2_WIDTH 7 +#define ASTEROID_2_ARRAY_SIZE 49 + +#define MAX_SHOTS 20 +#define ENDED_SHOT 255 +#define MAX_ASTEROIDS 10 + +#define SHOT_DELAY 12 +#define ASTEROID_FREQ 25 +#define SCROLL_SPEED 20 +#define ASTEROID_MIN_SPEED 5 +#define ASTEROID_MAX_SPEED 4 +#define SHIP_SAVE_TICKS 240 +#define INCREASE_GAME_SPEED 50 + +static const uint8_t SHIP[] = { + 0,1,1,0,0,0,0,0,0,0,0,0, + 1,1,1,1,0,0,1,1,1,0,0,0, + 0,1,1,1,1,1,1,1,1,1,0,0, + 0,0,1,1,1,1,1,1,1,1,1,0, + 0,0,1,1,1,1,1,1,1,1,1,1, + 0,0,1,1,1,1,1,1,1,1,1,0, + 0,1,1,1,1,1,1,1,1,1,0,0, + 1,1,1,1,0,0,1,1,1,0,0,0, + 0,1,1,0,0,0,0,0,0,0,0,0 +}; + +static const uint8_t ASTEROID_1[] = { + 0,1,1,0,0,0, + 0,1,1,1,0,1, + 1,1,1,1,1,1, + 0,1,1,1,1,0, + 0,1,1,1,1,0, + 0,0,1,0,0,0 +}; + +static const uint8_t ASTEROID_3[] = { + 0,1,1,0,0,0,0,0, + 0,1,1,1,0,1,1,1, + 1,1,1,1,1,1,1,1, + 0,1,1,1,1,1,1,0, + 0,1,1,1,1,1,0,0, + 1,1,1,1,1,1,1,0, + 1,1,0,1,1,1,1,1, + 0,0,0,1,1,1,0,0 +}; + +static const uint8_t ASTEROID_2[] = { + 0,0,0,0,1,1,0, + 0,1,1,1,1,1,1, + 1,1,1,1,1,1,1, + 0,1,1,1,1,0,0, + 0,0,1,1,0,0,0, + 0,0,1,1,1,0,0, + 0,0,0,1,0,0,0 +}; + +struct gamestate { + char player; + uint8_t ship[SHIP_ARRAY_SIZE]; + uint8_t ship_x; + uint8_t ship_y; + uint8_t shots_x[MAX_SHOTS]; + uint8_t shots_y[MAX_SHOTS]; + uint8_t shot_delay; + uint8_t asteroids_x[MAX_ASTEROIDS]; + uint8_t asteroids_y[MAX_ASTEROIDS]; + uint8_t asteroids_t[MAX_ASTEROIDS]; + uint8_t asteroids_s[MAX_ASTEROIDS]; + uint8_t asteroids_h[MAX_ASTEROIDS]; + uint32_t ticks; + uint32_t score; + uint8_t ships; + uint32_t ship_safe; + uint8_t ship_blinker; + uint8_t speed; + uint32_t highscore; +} game; +char key; + +static bool highscore_set(uint32_t score, char nick[]); +static uint32_t highscore_get(char nick[]); +static void init_game(); +static void conrtols(); +static bool screen_intro(); +static void draw_game(); + static void draw_ship(); + static void draw_score(); + static void draw_shots(); + static void draw_shot(); + static void draw_environ(); + static void draw_asteroid(); + static void draw_splash(); +static void shoot(); +static void make_asteroids(); +static void detect_collitions(); + +void ram(void){ + while(1) { + if (!screen_intro()) + return; + init_game(); + while(game.ships > 0){ + game.ticks++; + lcdFill(0); + conrtols(); + draw_game(); + lcdDisplay(); + delayms_queue_plus(12,0); + if(game.shot_delay > 0){ + game.shot_delay--; + } + } + draw_splash(); + } +}; + +static bool screen_intro(void) { + char key=0; + while(key==0) { + getInputWaitRelease(); + lcdFill(0); + int ct = 0; + for (int i = 0; i < SHIP_HEIGHT; i++){ + for(int d = 0; d < SHIP_WIDTH; d++){ + lcdSetPixel((40+d)%RESX,(10+i)%RESY,SHIP[ct]); + ct++; + } + } + DoString (13,25,"R0KET TYPE"); + uint32_t highscore; + char highnick[20]; + highscore = highscore_get(highnick); + DoInt(13, 40, highscore); + DoString (13, 50, highnick); + lcdDisplay(); + key=getInputWaitTimeout(1000); + } + //getInputWaitRelease(); + return !(key==BTN_LEFT); +} + +static void draw_splash(void){ + char key=0; + while(key==0) { + lcdFill(0); + if (highscore_set(game.score, GLOBAL(nickname))){ + DoString (16,15,"HIGHSCORE!"); + } else { + DoString (16,15, "GAME OVER"); + } + DoString (24,40, "GAME BY"); + DoString (10,50, "@RANZWERTIG"); + lcdDisplay(); + key=getInputWaitTimeout(1000); + } + return; +} + +static bool highscore_set(uint32_t score, char nick[]) { + MPKT * mpkt= meshGetMessage('r'); + if(MO_TIME(mpkt->pkt)>score) + return false; + + MO_TIME_set(mpkt->pkt,score); + strcpy((char*)MO_BODY(mpkt->pkt),nick); + if(GLOBAL(privacy)==0){ + uint32touint8p(GetUUID32(),mpkt->pkt+26); + mpkt->pkt[25]=0; + }; + return true; +} + +static uint32_t highscore_get(char nick[]){ + MPKT * mpkt= meshGetMessage('r'); + + strcpy(nick,(char*)MO_BODY(mpkt->pkt)); + + return MO_TIME(mpkt->pkt); +} + +static void init_game(void) { + + game.ticks = 0; + game.ships = 3; + game.score = 0; + game.speed = 0; + game.ship_x = 5; + game.ship_y = RESY/2; + game.ship_blinker = 0; + game.ship_safe = 0; + + for(int i = 0; i 0){ + game.ship_safe--; + } + if(game.ship_safe > 0 && game.ship_blinker == 0 && game.ship_safe%40 == 0){ + game.ship_blinker = 20; + } + if(game.ship_blinker > 0){ + game.ship_blinker--; + } + int ct = 0; + for (int i = 0; i < SHIP_HEIGHT; i++){ + for(int d = 0; d < SHIP_WIDTH; d++){ + if(game.ship_blinker > 0){ + } else { + lcdSetPixel((game.ship_x+d)%RESX,(game.ship_y+i)%RESY,SHIP[ct]); + } + ct++; + } + } +} + +static void draw_environ(void){ + if(game.ticks%INCREASE_GAME_SPEED+1 == 0){ + game.speed++; + } + for(int i = 0; i < MAX_ASTEROIDS;i++){ + if(game.asteroids_t[i] > 0){ + draw_asteroid(i); + int speed = game.ticks%game.asteroids_s[i]; + if(speed == 0) { + game.asteroids_x[i]--; + } + if(game.asteroids_x[i] == 0){ + game.asteroids_t[i] = 0; + } + } + } +} + +static void make_asteroids(void){ + int freq = ASTEROID_FREQ-game.speed; + if(freq < 1){ + freq = 1; + } + if(game.ticks%freq == 0){ + uint8_t rand_x = RESX+getRandom()%RESX; + uint8_t rand_y = getRandom()%RESY; + int as = 0; + for(int i = 0; i < MAX_ASTEROIDS;i++){ + if(game.asteroids_t[i] == 0){ + as = i; + } + } + game.asteroids_x[as] = rand_x; + game.asteroids_y[as] = rand_y; + game.asteroids_t[as] = getRandom()%3+1; + int speed = (getRandom()%ASTEROID_MIN_SPEED+ASTEROID_MAX_SPEED)-game.speed; + if(speed < 0){ + speed = 0; + } + game.asteroids_s[as] = speed; + + } +} + +static void draw_asteroid(int as){ + if(game.asteroids_t[as] > 0){ + int x = game.asteroids_x[as]; + int y = game.asteroids_y[as]; + + if(game.asteroids_t[as] == 1){ + int ct = 0; + for (int i = 0; i < ASTEROID_1_HEIGHT; i++){ + for(int d = 0; d < ASTEROID_1_WIDTH; d++){ + if(ASTEROID_1[ct] == 1){ + lcdSetPixel(x+d,y+i,1 && game.asteroids_h[as] == 0); + } + ct++; + } + } + } else if(game.asteroids_t[as] == 2){ + int ct = 0; + for (int i = 0; i < ASTEROID_2_HEIGHT; i++){ + for(int d = 0; d < ASTEROID_2_WIDTH; d++){ + if(ASTEROID_2[ct] == 1 && game.asteroids_h[as] == 0){ + lcdSetPixel(x+d,y+i,1); + } + if(ASTEROID_2[ct] == 1 && game.asteroids_h[as] == 1 && getRandom()%2 == 0){ + lcdSetPixel(x+d,y+i,1); + } + ct++; + } + } + } else if(game.asteroids_t[as] == 3){ + int ct = 0; + for (int i = 0; i < ASTEROID_3_HEIGHT; i++){ + for(int d = 0; d < ASTEROID_3_WIDTH; d++){ + if(ASTEROID_3[ct] == 1 && game.asteroids_h[as] == 0){ + lcdSetPixel(x+d,y+i,1); + } + if(ASTEROID_3[ct] == 1 && game.asteroids_h[as] == 1 && getRandom()%2 == 0){ + lcdSetPixel(x+d,y+i,1); + } + if(ASTEROID_3[ct] == 1 && game.asteroids_h[as] == 2 && getRandom()%4 == 0){ + lcdSetPixel(x+d,y+i,1); + } + ct++; + } + } + } + } +} + +static void draw_score(void){ + DoInt(2,2,game.score); + DoInt(RESX-8,2,game.ships); + DoString (RESX-20,2,"H"); +} + +static void detect_collitions(void){ + for(int i = 0;i 0){ + int as_h = 0; + int as_w = 0; + if(game.asteroids_t[i] == 1){ + as_h = ASTEROID_1_HEIGHT; + as_w = ASTEROID_1_WIDTH; + } else if(game.asteroids_t[i] == 2){ + as_h = ASTEROID_2_HEIGHT; + as_w = ASTEROID_2_WIDTH; + } else if(game.asteroids_t[i] == 3){ + as_h = ASTEROID_3_HEIGHT; + as_w = ASTEROID_3_WIDTH; + } + for(int z = 0; z= game.asteroids_y[i] && game.shots_y[z] <= game.asteroids_y[i]+as_h){ + if(game.shots_x[z] > game.asteroids_x[i]){ + game.asteroids_h[i]++; + game.shots_x[z] = 255; + game.shots_y[z] = 255; + if(game.asteroids_t[i] == game.asteroids_h[i]){ + game.score += game.asteroids_t[i]; + game.asteroids_x[i] = 255; + game.asteroids_y[i] = 255; + game.asteroids_t[i] = 0; + game.asteroids_s[i] = 0; + game.asteroids_h[i] = 0; + } + } + } + } + } + int xl = game.ship_x; + int yo = game.ship_y; + int xr = game.asteroids_x[i] + as_w; + int yu = game.asteroids_y[i] + as_h; + if(game.asteroids_x[i] < game.ship_x){ + xl = game.asteroids_x[i]; + } + if(game.asteroids_y[i] < game.ship_y){ + yo = game.asteroids_y[i]; + } + if(game.ship_x + SHIP_WIDTH > game.asteroids_x[i] + as_w){ + xr = game.ship_x + SHIP_WIDTH; + } + if(game.ship_y + SHIP_HEIGHT > game.asteroids_y[i] + as_h){ + yu = game.ship_y + SHIP_HEIGHT; + } + if(SHIP_WIDTH + as_w > xr - xl && SHIP_HEIGHT + as_h > yu - yo){ + if(game.ship_safe == 0){ + game.ships--; + game.asteroids_x[i] = 255; + game.asteroids_y[i] = 255; + game.asteroids_t[i] = 0; + game.asteroids_s[i] = 0; + game.ship_safe = SHIP_SAVE_TICKS; + } + } + } + } +} + +static void draw_shots() { + for(int i = 0; i 0){ + game.ship_x -= 1; + } + } else if (gpioGetValue(RB_BTN1)==0) { + if (game.ship_x < RESX-SHIP_WIDTH){ + game.ship_x += 1; + } + } else if (gpioGetValue(RB_BTN2)==0) { + if (game.ship_y < RESY-SHIP_HEIGHT){ + game.ship_y += 1; + } + } else if (gpioGetValue(RB_BTN3)==0) { + if (game.ship_y > 0){ + game.ship_y -= 1; + } + } else if (gpioGetValue(RB_BTN4)==0) { + shoot(); + } +} diff --git a/firmware/l0dable/worksh.c b/firmware/l0dable/worksh.c new file mode 100644 index 0000000..52a6008 --- /dev/null +++ b/firmware/l0dable/worksh.c @@ -0,0 +1,132 @@ +/* + * geigerct.c + * + * + * Created on: 11.08.2011 + * Author: Turbo J + * + * Implements simple Geiger Counter + * Counts rising edges on P3_0 = BUSINT + * so you can directly connect the Geiger board + * from http://mightyohm.com/blog/products/geiger-counter/ + * + */ + +#include +#include + +#include "basic/basic.h" +#include "basic/config.h" + +#include "lcd/render.h" +#include "lcd/print.h" + +#include "usetable.h" + +// Liberated from ARM Cortex M3 CMSIS core_cm3.h +// The processor definition headers for R0ket are incomplete :-/ + +#define __I +#define __IO volatile + +typedef struct { + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPU ID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt / Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) Hard Fault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) Mem Manage Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) Bus Fault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) ISA Feature Register */ +} SCB_Type; + +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ +#define SCB ((SCB_Type *) SCB_BASE) /*!< SCB configuration struct */ + +uint32_t VectorTableInRAM[73] __attribute__ ((aligned(1024))); // VTOR needs 1024 Byte alignment, see UM10375.PDF + +void (*orig_handler)(void); // original EINT3 handler + +void TIMER32_0_IRQHandler(void); + +// Remember: ram() must be the first function, place all other code AFTER +// because the Implementer seem not to know how to use section attributes + +static void mainloop(); + +void ram(void) { + uint8_t button; + uint32_t LEDs; + + // populate my Vector table + memcpy(VectorTableInRAM, 0, sizeof(VectorTableInRAM)); + orig_handler = (void*) VectorTableInRAM[TIMER_32_0_IRQn + 16]; + VectorTableInRAM[TIMER_32_0_IRQn + 16] = (uint32_t) &TIMER32_0_IRQHandler; + // HACK: use RAM vector table to implement own IRQ handler + SCB->VTOR = (uint32_t) &VectorTableInRAM[0]; + // TODO add DMB() here, as VTOR updates are NOT effective immediately + // + NVIC_EnableIRQ(TIMER_32_0_IRQn); + + /* Enable the clock for CT32B0 */ + SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT32B0); + TMR_TMR32B0MR0 = (72E6/5E3)/2; + TMR_TMR32B0MCR = (TMR_TMR32B0MCR_MR0_INT_ENABLED | TMR_TMR32B0MCR_MR0_RESET_ENABLED); + TMR_TMR32B0TCR = TMR_TMR32B0TCR_COUNTERENABLE_ENABLED; + + mainloop(); + + NVIC_DisableIRQ(TIMER_32_0_IRQn); + TMR_TMR32B0TCR = TMR_TMR32B0TCR_COUNTERENABLE_DISABLED; + // restore VTOR + SCB->VTOR = 0; + //TODO DMB(); Cortex Manual suggests DMB after setting VTOR + // not really needed in this case +} + +void TIMER32_0_IRQHandler(void) +{ + TMR_TMR32B0IR = TMR_TMR32B0IR_MR0; + static int time=0; + if (time==0){time=1;} else {time=0;} + gpioSetValue (RB_LED2, time); + gpioSetValue (RB_SPI_SS3, time); +} + +static void mainloop(void) { + int dx=0; + int dy=0; + static uint32_t ctr=0; + ctr++; + + setExtFont(GLOBAL(nickfont)); + dx=DoString(0,0,GLOBAL(nickname)); + dx=(RESX-dx)/2; + if(dx<0) + dx=0; + dy=(RESY-getFontHeight())/2; + + lcdClear(); + lcdSetPixel(1,1,1); + DoString(dx,dy,GLOBAL(nickname)); + lcdRefresh(); + + while(getInputRaw()==BTN_NONE){ + delayms_queue_plus(10,0); + }; + return; +} + +