#include #include #include #include "basic/basic.h" #include "funk/nrf24l01p.h" #include "lcd/lcd.h" //#include "usetable.h" #define AWAKE_PACKET_RETRIES 20 #define AWAKE_MIN_WINNERS 3 #define AWAKE_FONT_HEIGHT 8 typedef enum packet_type_e { PCKT_WINNER0, PCKT_WINNER1, PCKT_WINNER2, PCKT_WINNER3, PCKT_WINNER4, PCKT_WINNER5, PCKT_WINNER6, PCKT_WINNER7, PCKT_WAKEUP, PCKT_STANDBY, PCKT_NONE } packet_type_t; static char const *const awake_gPackets[] = { "winner0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "winner1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "winner2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "winner3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "winner4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "winner5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "winner6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "winner7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "wake up\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "standby\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" }; /** * Initializes wireless stuff. */ static void awake_initNrf(void) { nrf_init(); static struct NRF_CFG config = { .channel = 81, .txmac = "\x1\x2\x3\x2\x1", .nrmacs = 1, .mac0 = "\x1\x2\x3\x2\x1", .maclen = "\x20" }; nrf_config_set(&config); nrf_set_strength(3); } /** * Polls for a special packet which indicates the success of a player. */ static packet_type_t awake_waitForPacket(void) { uint8_t buffer[32]; if (nrf_rcv_pkt_time(100, 32, buffer) == 32) { for (packet_type_t p = PCKT_WINNER0; p < PCKT_NONE; ++p) { unsigned int bEqual = 1; for (unsigned int i = 0; i < 8; ++i) { if (buffer[i] != awake_gPackets[p][i]) { bEqual = 0; break; } } if (bEqual) { return p; } } } return PCKT_NONE; } /** * Waits for either pushed buttons or a signal on the hacker bus. */ static void awake_waitForKeyPressOrHackerbus(void) { gpioSetDir(RB_HB0, gpioDirection_Input); // watch out for pushed buttons and/or hacker bus activity while (gpioGetValue(RB_HB0) != 0) { if (getInput() != BTN_NONE) { getInputWaitRelease(); break; } } while (gpioGetValue(RB_HB0) == 0); } /** * The greeter! */ static void awake_promptUserBegin(void) { gpioSetDir(RB_HB0, gpioDirection_Input); lcdFill(0); DoString(0, 0, "Eine Taste"); DoString(0, 8, "druecken um"); DoString(0,16, "das Spiel"); DoString(0,24, "zu starten!"); lcdDisplay(); awake_waitForKeyPressOrHackerbus(); lcdFill(0); DoString(0, 0, "Spiel laeuft!"); DoString(0, 16, "FEUERTASTE"); DoString(0, 24, "fuer Standby"); lcdDisplay(); } /** * Informs about the happy end! */ static void awake_promptUserEnd(void){ lcdFill(0); DoString(0, 0, "Es wurden ge-"); DoString(0, 8, "nug Gewinner "); DoString(0, 16, "ermittelt! "); lcdDisplay(); // toggle RB_HB1 pin from 0V to 3,3 for 200ms GPIO_GPIO0DATA |= (1u << 10); delayms_queue(200); GPIO_GPIO0DATA &= ~(1u << 10); delayms_queue(200); } /** * Explains a brief moment of unresponsiveness. */ static void awake_promptStandby(void){ lcdFill(0); DoString(0, 0, "Bitte warten!"); DoString(0, 8, "Sende Standby"); DoString(0, 16, "Pakete... "); lcdDisplay(); } void awake_initHackerBus() { // set RB_HB1 to GPIO mode (output) #define IOCON_PIO0_10 (*((REG32*) (0x40044068))) IOCON_PIO0_10 &= ~(00000007); IOCON_PIO0_10 |= 0x00000001; GPIO_GPIO0DIR |= (1 << 10); GPIO_GPIO0DATA &= ~(1 << 10); } /** * Main function of the l0dable. */ void main_awake(void) { awake_initNrf(); awake_initHackerBus(); while (1) { awake_promptUserBegin(); uint8_t joyinput = BTN_NONE; unsigned int nWinnerFlags = 0, nWinnerCount = 0; while ((joyinput != BTN_ENTER) && (nWinnerCount < AWAKE_MIN_WINNERS)) { if ((joyinput = getInput()) != BTN_NONE) { getInputWaitRelease(); } // send a "wake up" packet every loop cycle so that in case a r0ket // is rebooted, the player can continue the game uint8_t packet[32]; memcpy(packet, awake_gPackets[PCKT_WAKEUP], 32); delayms(10); nrf_snd_pkt_crc(32, packet); // watch out for winners! packet_type_t const ePacket = awake_waitForPacket(); unsigned int const nWinnerMask = (1 << ePacket) & 0xFF; if ((ePacket <= PCKT_WINNER7) && !(nWinnerFlags & nWinnerMask)) { nWinnerFlags |= nWinnerMask; ++nWinnerCount; DoInt(0, 32, nWinnerCount); lcdDisplay(); } } if (nWinnerCount >= AWAKE_MIN_WINNERS) { awake_promptUserEnd(); } awake_promptStandby(); uint8_t packet[32]; for (int i = 0; i < AWAKE_PACKET_RETRIES; ++i) { delayms_queue(50); memcpy(packet, awake_gPackets[PCKT_STANDBY], 32); nrf_snd_pkt_crc(32, packet); } } return; }