crashtest-r0ket/firmware/applications/awake.c

215 lines
4.7 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
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);
awake_waitForKeyPressOrHackerbus();
}
/**
* 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;
DoIntX(0, 32, nWinnerMask);
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;
}