Swadge 2024 2.0.0
APIs to develop games for the Magfest Swadge
Loading...
Searching...
No Matches
swadge2024.h File Reference

Detailed Description

Design Philosophy

A Swadge mode is struct of configuration variables and function pointers, which is the closest thing in C to an object. These provide a common interface so that the system firmware can run each mode. The Swadge's system firmware will initialize peripherals required by the mode and call the mode's function pointers when appropriate.

If a mode does not need a particular function, for example it doesn't do audio handling, it is safe to set the function pointer to NULL. The function won't be called. All fields must be initialized to something, since an uninitialized field may lead to undefined behavior.

Note
The details of all configuration variables and function pointers can be found in swadgeMode_t.

The top level menu will maintain a list of all available modes and the user can pick the mode to run. This approach is similar to apps. Only one mode may run at a single time, and when it runs it will have full system resources.

Usage

Each mode must have a single swadgeMode_t. How the Swadge mode works is flexible and left up to the mode's author to determine. Maybe it uses a menu.h, maybe it has a custom UI. All Swadge mode source code should be in the /main/modes folder. Each mode should have it's own folder to keep source organized.

To build the firmware, the mode's source files must be added to /main/CMakeLists.txt. The emulator's makefile automatically finds files to compile recursively, so they do not need to be explicitly listed.

It's best practice not to use 'generic' names for functions and variables, because they may collide with another mode's functions or variables. When possible, functions and variables should be prefixed with something unique, like demo in the example below.

Example

Adding a mode to the CMakeFile requires adding two separate lines in the idf_component_register section.

"modes/pong/pong.c"

under the SRCS section and

"modes/pong"

under the INCLUDES section.

Function prototypes must be declared before using them to initialize function pointers:

// It's good practice to declare immutable strings as const so they get placed in ROM, not RAM
static const char demoName[] = "Demo";
static void demoEnterMode(void);
static void demoExitMode(void);
static void demoMainLoop(int64_t elapsedUs);
static void demoAudioCallback(uint16_t* samples, uint32_t sampleCnt);
static void demoBackgroundDrawCallback(int16_t x, int16_t y, int16_t w, int16_t h, int16_t up, int16_t upNum);
static void demoEspNowRecvCb(const esp_now_recv_info_t* esp_now_info, const uint8_t* data, uint8_t len, int8_t rssi);
static void demoEspNowSendCb(const uint8_t* mac_addr, esp_now_send_status_t status);
static int16_t demoAdvancedUSB(uint8_t* buffer, uint16_t length, uint8_t isGet);
static void demoDacCb(uint8_t *samples, int16_t len);

Then functions can be used to initialize a swadgeMode_t:

swadgeMode_t demoMode = {
.modeName = demoName,
.wifiMode = ESP_NOW,
.overrideUsb = false,
.usesAccelerometer = true,
.usesThermometer = true,
.overrideSelectBtn = false,
.fnEnterMode = demoEnterMode,
.fnExitMode = demoExitMode,
.fnMainLoop = demoMainLoop,
.fnAudioCallback = demoAudioCallback,
.fnBackgroundDrawCallback = demoBackgroundDrawCallback,
.fnEspNowRecvCb = demoEspNowRecvCb,
.fnEspNowSendCb = demoEspNowSendCb,
.fnAdvancedUSB = demoAdvancedUSB,
.fnDacCb = demoDacCb,
};
@ ESP_NOW
ESP-NOW packets are delivered to Swadge modes from the main loop.
Definition hdw-esp-now.h:101
A struct of all the function pointers necessary for a swadge mode. If a mode does not need a particul...
Definition swadge2024.h:233
const char * modeName
This swadge mode's name, used in menus. This is not a function pointer.
Definition swadge2024.h:237

The declared functions must actually exist somewhere:

static void demoEnterMode(void)
{
// Fill this in
}
static void demoExitMode(void)
{
// Fill this in
}
static void demoMainLoop(int64_t elapsedUs)
{
// Fill this in
}
static void demoAudioCallback(uint16_t* samples, uint32_t sampleCnt)
{
// Fill this in
}
static void demoBackgroundDrawCallback(int16_t x, int16_t y, int16_t w, int16_t h, int16_t up, int16_t upNum)
{
// Fill this in
}
static void demoEspNowRecvCb(const esp_now_recv_info_t* esp_now_info, const uint8_t* data, uint8_t len, int8_t rssi)
{
// Fill this in
}
static void demoEspNowSendCb(const uint8_t* mac_addr, esp_now_send_status_t status)
{
// Fill this in
}
static int16_t demoAdvancedUSB(uint8_t* buffer, uint16_t length, uint8_t isGet)
{
// Fill this in
return 0;
}
static void demoDacCb(uint8_t *samples, int16_t len)
{
// Fill this in
}

The swadgeMode_t should be declared as extern in a header file so that it can be referenced in the main menu

#ifndef _DEMO_MODE_H_
#define _DEMO_MODE_H_
#include "swadge2024.h"
extern swadgeMode_t demoMode;
#endif

Add the mode to the menu initializer in mainMenuEnterMode():

#include "demoMode.h"
addSingleItemToMenu(mainMenu->menu, demoMode.modeName);
menuItem_t * addSingleItemToMenu(menu_t *menu, const char *label)
Add a single item entry to the menu. When this item is selected, the menuCb callback is called with t...
Definition menu.c:193

Add the mode to the selector logic in mainMenuCb():

else if (label == demoMode.modeName)
{
switchToSwadgeMode(&demoMode);
}
void switchToSwadgeMode(swadgeMode_t *mode)
Definition swadge2024.c:688

Go to the source code of this file.

Data Structures

struct  swadgeMode_t
 A struct of all the function pointers necessary for a swadge mode. If a mode does not need a particular function, for example it doesn't do audio handling, it is safe to set the pointer to NULL. It just won't be called. More...
 

Macros

#define EXIT_TIME_US   1000000
 
#define DEFAULT_FRAME_RATE_US   40000
 the default time between drawn frames, in microseconds
 

Functions

bool checkButtonQueueWrapper (buttonEvt_t *evt)
 Service the queue of button events that caused interrupts This only returns a single event, even if there are multiple in the queue This function may be called multiple times in a row to completely empty the queue.
 
void switchToSwadgeMode (swadgeMode_t *mode)
 
void softSwitchToPendingSwadge (void)
 Switch to the pending Swadge mode without restarting the system.
 
void deinitSystem (void)
 Deinitialize all components in the system.
 
void openQuickSettings (void)
 
void setFrameRateUs (uint32_t newFrameRateUs)
 Set the framerate, in microseconds.
 
uint32_t getFrameRateUs (void)
 Get the current framerate, in microseconds.
 

Macro Definition Documentation

◆ EXIT_TIME_US

#define EXIT_TIME_US   1000000

◆ DEFAULT_FRAME_RATE_US

#define DEFAULT_FRAME_RATE_US   40000

the default time between drawn frames, in microseconds

Function Documentation

◆ checkButtonQueueWrapper()

bool checkButtonQueueWrapper ( buttonEvt_t * evt)

Service the queue of button events that caused interrupts This only returns a single event, even if there are multiple in the queue This function may be called multiple times in a row to completely empty the queue.

This is a wrapper for checkButtonQueue() which also monitors the button to return to the main menu

Parameters
evtIf an event occurred, return it through this argument
Returns
true if an event occurred, false if nothing happened

◆ switchToSwadgeMode()

void switchToSwadgeMode ( swadgeMode_t * mode)

Set up variables to synchronously switch the swadge mode in the main loop

Parameters
modeA pointer to the mode to switch to

◆ softSwitchToPendingSwadge()

void softSwitchToPendingSwadge ( void )

Switch to the pending Swadge mode without restarting the system.

◆ deinitSystem()

void deinitSystem ( void )

Deinitialize all components in the system.

◆ openQuickSettings()

void openQuickSettings ( void )

◆ setFrameRateUs()

void setFrameRateUs ( uint32_t newFrameRateUs)

Set the framerate, in microseconds.

Parameters
newFrameRateUsThe time between frame draws, in microseconds

◆ getFrameRateUs()

uint32_t getFrameRateUs ( void )

Get the current framerate, in microseconds.

Returns
uint32_t The time between frame draws, in microseconds