refact0red awake-app, standby-packets are now sent continously

This commit is contained in:
tunix 2012-06-17 22:49:06 +02:00
parent 50f14a3a5e
commit ab1870534e
1 changed files with 118 additions and 80 deletions

View File

@ -10,21 +10,29 @@
#define AWAKE_PACKET_RETRIES 20 #define AWAKE_PACKET_RETRIES 20
#define AWAKE_MIN_WINNERS 3 #define AWAKE_MIN_WINNERS 3
#define AWAKE_FONT_HEIGHT 8 #define AWAKE_FONT_HEIGHT 8
#define BTN_HBUS (1 << 7)
typedef enum packet_type_e { typedef enum awake_state_e {
PCKT_WINNER0, AWAKE_STATE_STANDBY,
PCKT_WINNER1, AWAKE_STATE_PLAYING,
PCKT_WINNER2, AWAKE_STATE_WON
PCKT_WINNER3, } awake_state_t;
PCKT_WINNER4,
PCKT_WINNER5,
PCKT_WINNER6, typedef enum awake_packet_e {
PCKT_WINNER7, AWAKE_PCKT_WINNER0,
PCKT_WAKEUP, AWAKE_PCKT_WINNER1,
PCKT_STANDBY, AWAKE_PCKT_WINNER2,
PCKT_NONE AWAKE_PCKT_WINNER3,
} packet_type_t; 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[] = { static char const *const awake_gPackets[] = {
@ -61,10 +69,10 @@ static void awake_initNrf(void) {
/** /**
* Polls for a special packet which indicates the success of a player. * Polls for a special packet which indicates the success of a player.
*/ */
static packet_type_t awake_waitForPacket(void) { static awake_packet_t awake_waitForPacket(void) {
uint8_t buffer[32]; uint8_t buffer[32];
if (nrf_rcv_pkt_time(100, 32, buffer) == 32) { if (nrf_rcv_pkt_time(100, 32, buffer) == 32) {
for (packet_type_t p = PCKT_WINNER0; p < PCKT_NONE; ++p) { for (awake_packet_t p = AWAKE_PCKT_WINNER0; p < AWAKE_PCKT_NONE; ++p) {
unsigned int bEqual = 1; unsigned int bEqual = 1;
for (unsigned int i = 0; i < 8; ++i) { for (unsigned int i = 0; i < 8; ++i) {
if (buffer[i] != awake_gPackets[p][i]) { if (buffer[i] != awake_gPackets[p][i]) {
@ -77,45 +85,49 @@ static packet_type_t awake_waitForPacket(void) {
} }
} }
} }
return PCKT_NONE; return AWAKE_PCKT_NONE;
} }
/** /**
* Waits for either pushed buttons or a signal on the hacker bus. * Checks for pushed buttons and signals on RB_HB0.
*/ */
static void awake_waitForKeyPressOrHackerbus(void) { static uint8_t awake_getInputNonBlocking(void) {
gpioSetDir(RB_HB0, gpioDirection_Input); volatile uint32_t rb_hb0 = gpioGetValue(RB_HB0);
// watch out for pushed buttons and/or hacker bus activity if (rb_hb0 == 0) {
while (gpioGetValue(RB_HB0) != 0) { while (gpioGetValue(RB_HB0) == 0);
if (getInput() != BTN_NONE) { return BTN_HBUS;
} else {
uint8_t input = getInput();
if (input != BTN_NONE) {
getInputWaitRelease(); getInputWaitRelease();
break;
} }
return input;
} }
while (gpioGetValue(RB_HB0) == 0);
} }
/** /**
* The greeter! * The greeter!
*/ */
static void awake_promptUserBegin(void) { static void awake_promptBegin(void) {
gpioSetDir(RB_HB0, gpioDirection_Input);
lcdFill(0); lcdFill(0);
DoString(0, 0, "Eine Taste"); DoString(0, 0, "Standby-Modus");
DoString(0, 8, "druecken um"); DoString(0,16, "Override mit");
DoString(0,16, "das Spiel"); DoString(0,24, "Tastendruck.");
DoString(0,24, "zu starten!");
lcdDisplay(); lcdDisplay();
}
awake_waitForKeyPressOrHackerbus();
/**
* You don't say?
*/
static void awake_promptGameRunning(void) {
lcdFill(0); lcdFill(0);
DoString(0, 0, "Spiel laeuft!"); DoString(0, 0, "Spiel laeuft!");
DoString(0, 16, "FEUERTASTE"); DoString(0, 16, "FEUERTASTE");
DoString(0, 24, "fuer Standby"); DoString(0, 24, "fuer Standby");
DoInt(0, 32, 0);
lcdDisplay(); lcdDisplay();
} }
@ -129,8 +141,30 @@ static void awake_promptUserEnd(void){
DoString(0, 8, "nug Gewinner "); DoString(0, 8, "nug Gewinner ");
DoString(0, 16, "ermittelt! "); DoString(0, 16, "ermittelt! ");
lcdDisplay(); lcdDisplay();
}
// toggle RB_HB1 pin from 0V to 3,3 for 200ms
/**
* 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); GPIO_GPIO0DATA |= (1u << 10);
delayms_queue(200); delayms_queue(200);
GPIO_GPIO0DATA &= ~(1u << 10); GPIO_GPIO0DATA &= ~(1u << 10);
@ -139,72 +173,76 @@ static void awake_promptUserEnd(void){
/** /**
* Explains a brief moment of unresponsiveness. * Sends the specified packet.
* @param packet_type The kind of packet to be sent.
*/ */
static void awake_promptStandby(void){ static void awake_sendPacket(awake_packet_t packet_type) {
lcdFill(0); uint8_t packet[32];
DoString(0, 0, "Bitte warten!"); memcpy(packet, awake_gPackets[packet_type], 32);
DoString(0, 8, "Sende Standby"); nrf_snd_pkt_crc(32, packet);
DoString(0, 16, "Pakete... "); delayms(10);
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. * Main function of the l0dable.
*/ */
void main_awake(void) { void main_awake(void) {
awake_initNrf(); awake_initNrf();
awake_initHackerBus(); awake_initHackerBus();
unsigned int nWinnerFlags = 0, nWinnerCount = 0;
awake_state_t state = AWAKE_STATE_STANDBY;
while (1) { while (1) {
awake_promptUserBegin(); switch (state) {
uint8_t joyinput = BTN_NONE; case AWAKE_STATE_STANDBY:
unsigned int nWinnerFlags = 0, nWinnerCount = 0; awake_promptBegin();
while ((joyinput != BTN_ENTER) && (nWinnerCount < AWAKE_MIN_WINNERS)) { // wait for key press or hacker bus signal
if ((joyinput = getInput()) != BTN_NONE) { while (awake_getInputNonBlocking() == BTN_NONE) {
getInputWaitRelease(); awake_sendPacket(AWAKE_PCKT_STANDBY);
delayms(50);
} }
state = AWAKE_STATE_PLAYING;
break;
// send a "wake up" packet every loop cycle so that in case a r0ket case AWAKE_STATE_PLAYING:
// is rebooted, the player can continue the game nWinnerFlags = 0;
uint8_t packet[32]; nWinnerCount = 0;
memcpy(packet, awake_gPackets[PCKT_WAKEUP], 32); awake_promptGameRunning();
delayms(10); while (state == AWAKE_STATE_PLAYING) {
nrf_snd_pkt_crc(32, packet); // 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! // watch out for winners!
packet_type_t const ePacket = awake_waitForPacket(); const awake_packet_t ePacket = awake_waitForPacket();
unsigned int const nWinnerMask = (1 << ePacket) & 0xFF; const unsigned int nWinnerMask = (1 << ePacket) & 0xFF;
if ((ePacket <= PCKT_WINNER7) && !(nWinnerFlags & nWinnerMask)) { if ((ePacket <= AWAKE_PCKT_WINNER7) &&
nWinnerFlags |= nWinnerMask; !(nWinnerFlags & nWinnerMask)) {
++nWinnerCount; nWinnerFlags |= nWinnerMask;
DoInt(0, 32, nWinnerCount); DoInt(0, 32, nWinnerCount);
lcdDisplay(); lcdDisplay();
if (++nWinnerCount >= AWAKE_MIN_WINNERS) {
state = AWAKE_STATE_WON;
}
}
}
} }
} break;
if (nWinnerCount >= AWAKE_MIN_WINNERS) { case AWAKE_STATE_WON:
awake_promptUserEnd(); awake_promptUserEnd();
} awake_toggleRbHb1();
state = AWAKE_STATE_STANDBY;
break;
awake_promptStandby(); default:
uint8_t packet[32]; state = AWAKE_STATE_STANDBY;
for (int i = 0; i < AWAKE_PACKET_RETRIES; ++i) { break;
delayms_queue(50);
memcpy(packet, awake_gPackets[PCKT_STANDBY], 32);
nrf_snd_pkt_crc(32, packet);
} }
} }
return;
} }