#include #include "basic/basic.h" #include "basic/byteorder.h" #include "lcd/lcd.h" #include "lcd/print.h" #include "funk/nrf24l01p.h" #include #include "basic/random.h" #include "basic/config.h" #include "usetable.h" //channel and mac used to transmit game announcements #define ANNOUNCE_CHANNEL 87 #define ANNOUNCE_MAC "REM0T" struct NRF_CFG config; struct packet{ uint8_t len; uint8_t protocol; uint8_t command; uint32_t id; uint32_t ctr; //union with 19 bytes data union content{ struct button{ uint8_t button; uint8_t reserved[18]; }__attribute__((packed)) button; struct text{ uint8_t x; uint8_t y; uint8_t flags; uint8_t text[16]; }__attribute__((packed)) text; struct nick{ uint8_t flags; uint8_t nick[18]; }__attribute__((packed)) nick; struct nickrequest{ uint8_t reserved[19]; }__attribute__((packed)) nickrequest; struct ack{ uint8_t flags; uint8_t reserved[18]; }__attribute__((packed)) ack; struct announce{ uint8_t gameMac[5]; uint8_t gameChannel; //uint8_t playerMac[5]; playerMac = gameMac+1; uint16_t gameId; uint8_t gameFlags; uint8_t interval; uint8_t jitter; uint8_t gameTitle[8]; }__attribute__((packed)) announce; struct join{ uint16_t gameId; uint8_t reserved[17]; }__attribute__((packed)) join; }c; uint16_t crc; }__attribute__((packed)); #define FLAGS_MASS_GAME 1 #define FLAGS_SHORT_PACKET 2 #define FLAGS_LONG_RECV 4 #define FLAGS_ACK_JOINOK 1 #define MASS_ID 1 #define FLAGS_CLS 1 /**************************************************************************/ /* l0dable for playing games which are announced by other r0kets with the l0dabel r_game */ /* Values of buf[3]: * B: packet sent by player, contain information which button is pressed * T: packet sent by game, contain text for display * N: packet sent by game, requesting nick * n: packet sent player, containing nick * A: packet sent by game, announcing game * J: packet sent by player, requesting to join game * a: ack, packet with $ctr was received */ uint32_t ctr; uint32_t id; uint16_t gameId; uint8_t interval; uint8_t jitter; uint8_t flags; uint8_t *gameTitle; void sendButton(uint8_t button); void sendJoin(uint32_t game); void processPacket(struct packet *p); void processAnnounce(struct announce *a); void processText(struct text *t); uint8_t selectGame(); void playGame(); struct announce games[7]; uint8_t gamecount; void ram(void) { int priv = GLOBAL(privacy); GLOBAL(privacy) = 3; config.nrmacs=1; config.maclen[0] = 32; config.channel = ANNOUNCE_CHANNEL; memcpy(config.mac0, ANNOUNCE_MAC, 5); nrf_config_set(&config); id = getRandom(); ctr = 1; while( selectGame() ){ playGame(); } GLOBAL(privacy) = priv; }; void playGame(void) { int len; struct packet p; lcdPrintln("Now playing:"); lcdPrintln(gameTitle); lcdRefresh(); while(1){ uint8_t button = getInputRaw(); sendButton(button); while(1){ if( flags & FLAGS_LONG_RECV ) len = nrf_rcv_pkt_time(64,sizeof(p),(uint8_t*)&p); else len = nrf_rcv_pkt_time(32,sizeof(p),(uint8_t*)&p); if(len==sizeof(p)){ processPacket(&p); }else{ break; } } int rnd = getRandom() % jitter; delayms(interval*5+rnd); volatile uint16_t i; i = getRandom()&0xfff; while(i--); }; } void showGames(uint8_t selected) { int i; lcdClear(); lcdPrintln("Games:"); if( gamecount ){ for(i=0;i 0 ){ selected--; } break; case BTN_LEFT: return 0; case BTN_ENTER: case BTN_RIGHT: if( gamecount == 0 ) return 0; gameId = games[selected].gameId; memcpy(config.txmac, games[selected].gameMac, 5); memcpy(config.mac0, games[selected].gameMac, 5); config.mac0[4]++; config.channel = games[selected].gameChannel; interval = games[selected].interval; jitter = games[selected].jitter; flags = games[selected].gameFlags; gameTitle = games[selected].gameTitle; nrf_config_set(&config); lcdClear(); if( games[selected].gameFlags & FLAGS_MASS_GAME ) return 1; else return joinGame(); } } } void processNickRequest( struct nickrequest *nq) { struct packet p; memset((void*)&p, 0, sizeof(p)); p.len=sizeof(p); p.protocol='G'; // Proto p.command='n'; p.id= id; p.ctr= ++ctr; p.c.nick.flags = 0; uint8_t *nick = GLOBAL(nickname); strcpy(p.c.nick.nick, nick); nrf_snd_pkt_crc(sizeof(p),(uint8_t*)&p); } void processPacket(struct packet *p) { if ((p->len==32) && (p->protocol=='G') && (p->id == id || p->id == 0) ){ //check sanity, protocol, id if (p->command=='T'){ struct packet ack; memset((void*)&ack, 0, sizeof(ack)); ack.len=sizeof(ack); ack.protocol='G'; ack.command='a'; ack.id= id; ack.ctr= p->ctr; ack.c.ack.flags = 0; if( p->id ) nrf_snd_pkt_crc(sizeof(ack),(uint8_t*)&ack); processText(&(p->c.text)); } else if (p->command=='N'){ processNickRequest(&(p->c.nickrequest)); } else if (p->command=='A'){ processAnnounce(&(p->c.announce)); } } } void processAnnounce(struct announce *a) { if( gamecount < sizeof(games)/sizeof(games[0]) ){ int repeat=0; int i; for (i=0; igameId == games[i].gameId){ repeat=1; } } if (repeat!=1){ games[gamecount] = *a; gamecount++; } } } void processText(struct text *t) { if( t->flags & FLAGS_CLS ) lcdClear() ; lcdSetCrsr(t->x, t->y); t->text[16] = 0; lcdPrint(t->text); lcdRefresh(); } //increment ctr and send button state, id and ctr void sendButton(uint8_t button) { struct packet p; memset((void*)&p, 0, sizeof(p)); p.len=sizeof(p); p.protocol='G'; // Proto p.command='B'; p.id= id; p.ctr= ++ctr; p.c.button.button=button; //lcdClear(); //lcdPrint("Key:"); lcdPrintInt(buf[2]); lcdNl(); if( flags & FLAGS_SHORT_PACKET ) nrf_snd_pkt_crc(16,(uint8_t*)&p); else nrf_snd_pkt_crc(sizeof(p),(uint8_t*)&p); }