#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 #define BTN_HBUS (1 << 7) typedef enum awake_state_e { AWAKE_STATE_STANDBY, AWAKE_STATE_PLAYING, AWAKE_STATE_WON } awake_state_t; typedef enum awake_packet_e { AWAKE_PCKT_WINNER0, AWAKE_PCKT_WINNER1, AWAKE_PCKT_WINNER2, AWAKE_PCKT_WINNER3, AWAKE_PCKT_WINNER4, AWAKE_PCKT_WINNER5, AWAKE_PCKT_WINNER6, AWAKE_PCKT_WINNER7, AWAKE_PCKT_WAKEUP, AWAKE_PCKT_STANDBY, AWAKE_PCKT_NONE } awake_packet_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 awake_packet_t awake_waitForPacket(void) { uint8_t buffer[32]; if (nrf_rcv_pkt_time(100, 32, buffer) == 32) { for (awake_packet_t p = AWAKE_PCKT_WINNER0; p < AWAKE_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 AWAKE_PCKT_NONE; } /** * Checks for pushed buttons and signals on RB_HB0. */ static uint8_t awake_getInputNonBlocking(void) { volatile uint32_t rb_hb0 = gpioGetValue(RB_HB0); if (rb_hb0 == 0) { while (gpioGetValue(RB_HB0) == 0); return BTN_HBUS; } else { uint8_t input = getInput(); if (input != BTN_NONE) { getInputWaitRelease(); } return input; } } /** * The greeter! */ static void awake_promptBegin(void) { lcdFill(0); DoString(0, 0, "Standby-Modus"); DoString(0,16, "Override mit"); DoString(0,24, "Tastendruck."); lcdDisplay(); } /** * You don't say? */ static void awake_promptGameRunning(void) { lcdFill(0); DoString(0, 0, "Spiel laeuft!"); DoString(0, 16, "FEUERTASTE"); DoString(0, 24, "fuer Standby"); DoInt(0, 32, 0); 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(); } /** * Prepare hacker bus for our evil plans. */ static void awake_initHackerBus(void) { // set RB_HB0 to input mode gpioSetDir(RB_HB0, gpioDirection_Input); // set RB_HB1 to GPIO mode... #define IOCON_PIO0_10 (*((REG32*) (0x40044068))) IOCON_PIO0_10 &= ~(00000007); IOCON_PIO0_10 |= 0x00000001; // ...and to output low GPIO_GPIO0DIR |= (1 << 10); GPIO_GPIO0DATA &= ~(1 << 10); } /** * Toggle RB_HB1 pin from 0V to 3,3 for 200ms. */ static void awake_toggleRbHb1(void) { GPIO_GPIO0DATA |= (1u << 10); delayms_queue(200); GPIO_GPIO0DATA &= ~(1u << 10); delayms_queue(200); } /** * Sends the specified packet. * @param packet_type The kind of packet to be sent. */ static void awake_sendPacket(awake_packet_t packet_type) { uint8_t packet[32]; memcpy(packet, awake_gPackets[packet_type], 32); nrf_snd_pkt_crc(32, packet); delayms(10); } /** * Main function of the l0dable. */ void main_awake(void) { awake_initNrf(); awake_initHackerBus(); unsigned int nWinnerFlags = 0, nWinnerCount = 0; awake_state_t state = AWAKE_STATE_STANDBY; while (1) { switch (state) { case AWAKE_STATE_STANDBY: awake_promptBegin(); // wait for key press or hacker bus signal while (awake_getInputNonBlocking() == BTN_NONE) { awake_sendPacket(AWAKE_PCKT_STANDBY); delayms(50); } state = AWAKE_STATE_PLAYING; break; case AWAKE_STATE_PLAYING: nWinnerFlags = 0; nWinnerCount = 0; awake_promptGameRunning(); while (state == AWAKE_STATE_PLAYING) { // check for manual override if (awake_getInputNonBlocking() != BTN_NONE) { // manual override -> back to standby mode state = AWAKE_STATE_STANDBY; } else { // send a wake up packet awake_sendPacket(AWAKE_PCKT_WAKEUP); // watch out for winners! const awake_packet_t ePacket = awake_waitForPacket(); const unsigned int nWinnerMask = (1 << ePacket) & 0xFF; if ((ePacket <= AWAKE_PCKT_WINNER7) && !(nWinnerFlags & nWinnerMask)) { nWinnerFlags |= nWinnerMask; DoInt(0, 32, nWinnerCount); lcdDisplay(); if (++nWinnerCount >= AWAKE_MIN_WINNERS) { state = AWAKE_STATE_WON; } } } } break; case AWAKE_STATE_WON: awake_promptUserEnd(); awake_toggleRbHb1(); state = AWAKE_STATE_STANDBY; break; default: state = AWAKE_STATE_STANDBY; break; } } }