215 lines
4.7 KiB
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;
|
|
}
|