crashtest-r0ket/firmware/applications/awake.c

249 lines
5.3 KiB
C

#include <sysinit.h>
#include <stdint.h>
#include <string.h>
#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;
}
}
}