Swadge 2024 2.0.0
APIs to develop games for the Magfest Swadge
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
swadgePass.h File Reference

Detailed Description

Design Philosophy

SwadgePass is a feature where Swadges can transmit and receive small packets of data while idle. This feature was inspired by Nintendo's StreetPass. SwadgePass data may include things like avatar data or high scores from all Swadge Modes.

SwadgePass uses ESP-NOW, not WiFi or Bluetooth. See hdw-esp-now.h.

Transmission and Reception

Packets are transmitted with sendSwadgePass(). To preserve battery life, this should only be called when the Swadge is idling in it's LED animation mode (dance.c). In this state, the Swadge will transmit every 7.5s, +/- 1.875s. Randomness ensures two Swadges don't get locked out-of-sync while transmitting and receiving. After transmitting, the Swadge stays awake and listening for 700ms. While not transmitting or listening, the Swadge light sleeps for 100ms increments, updating the LEDs ten times per second.

The receiver is initialized with initSwadgePassReceiver() and packets are received with receiveSwadgePass(). Any incoming packet may be passed to this function, including from modes which are using ESP-NOW for other purposes, as long as the receiver was initialized. deinitSwadgePassReceiver() frees memory allocated for the receiver.

During normal operation, if not explicitly used the WiFi radio is turned off and SwadgePass data is neither transmitted nor received.

Usage

Transmission and reception of SwadgePass data is automatic in dance.c and does not need to be managed by each SwadgeMode (see Transmission and Reception). Other modes may transmit and receive SwadgePass data, but it is discouraged for battery reasons.

Building a Packet for Transmission

A swadgePassPacket_t is built with the function fillSwadgePassPacket(), which calls each mode's swadgeMode_t.fnAddToSwadgePassPacket function. Each mode may add data to swadgePassPacket_t, and modes must not modify data which is not their own. The total packet size must be less than 250 bytes, which is the largest possible ESP-NOW packet.

Warning
swadgeMode_t.fnAddToSwadgePassPacket is called when the Swadge Mode is not initialized, so it must not rely on memory allocated or data loaded in swadgeMode_t.fnEnterMode

Using Received SwadgePass Data

Swadge Modes may check received SwadgePass data by giving an empty list_t to getSwadgePasses() to fill. getSwadgePasses() may fill the list with all received SwadgePass data, or only SwadgePass data which has not been used by the given mode yet. After being filled, the list contain pointers to swadgePassData_t and may be iterated through. swadgePassData_t.key is the string representation of the source MAC address. SwadgePass data will not change during Swadge Modes (aside from dance.c), so the data should be loaded once and saved for the mode's lifetime. getSwadgePasses() should not be called repeatedly.

If the Swadge Mode wants to use each SwadgePass data from a source only once, it can be checked with isPacketUsedByMode(). This may be useful for an RPG game where each received SwadgePass gets to make one action. Once the data is used, it can be marked as such with setPacketUsedByMode(). This will save the used state to non-volatile storage, which persists reboots.

When the Swadge Mode is finished with the SwadgePass data, it must be freed with freeSwadgePasses().

Example

Building a Packet for Transmission Example

swadgeMode_t.fnAddToSwadgePassPacket would be set to this example function.

void myModeAddToSwadgePassPacket(struct swadgePassPacket* packet)
{
// The field name should indicate which mode the data is for
// This is an example, your high score probably shouldn't be hardcoded
packet->myHighScore = 9001;
}
A SwadgePass packet which is transmitted over ESP NOW.
Definition swadgePass.h:120

Using Received SwadgePass Data Example

// Get all SwadgePasses, including used ones
list_t spList = {0};
getSwadgePasses(&spList, &myMode, true);
// Iterate through the list
node_t* spNode = spList.first;
while (spNode)
{
// Make a convenience pointer to the data in this node
// If the data hasn't been used yet
if (!isPacketUsedByMode(spd, &myMode))
{
// Print some packet data
ESP_LOGI("SP", "Receive from %s. Preamble is %d", spd->key, spd->data.packet.preamble);
// Mark the packet as used
setPacketUsedByMode(spd, &myMode, true);
}
// Iterate to the next data
spNode = spNode->next;
}
struct node * next
The next node in the list.
Definition linked_list.h:79
struct node node_t
A node in a doubly linked list with pointers to the previous and next values (which may be NULL),...
void * val
A pointer to the data for this node.
Definition linked_list.h:78
node_t * first
The first node in the list.
Definition linked_list.h:88
A doubly linked list with pointers to the first and last nodes.
Definition linked_list.h:87
void getSwadgePasses(list_t *swadgePasses, const struct swadgeMode *mode, bool getUsed)
Fill a list with SwadgePass data. The list should be empty before calling this function.
Definition swadgePass.c:246
bool isPacketUsedByMode(swadgePassData_t *data, const struct swadgeMode *mode)
Return if a given mode has used this SwadgePass data yet.
Definition swadgePass.c:314
void setPacketUsedByMode(swadgePassData_t *data, const struct swadgeMode *mode, bool isUsed)
Set if a given mode has used this SwadgePass data yet.
Definition swadgePass.c:329
SwadgePass data that is received from another Swadge.
Definition swadgePass.h:148

Go to the source code of this file.

Data Structures

struct  swadgePassPacket
 A SwadgePass packet which is transmitted over ESP NOW. More...
 
struct  swadgePassNvs_t
 SwadgePass data that is saved to NVS. More...
 
struct  swadgePassData_t
 SwadgePass data that is received from another Swadge. More...
 
struct  swadgePassPacket.swadgeIt
 
struct  swadgePassPacket.roboRunner
 

Typedefs

typedef struct swadgePassPacket swadgePassPacket_t
 A SwadgePass packet which is transmitted over ESP NOW.
 

Functions

void initSwadgePassReceiver (void)
 Initialize the SwadgePass receiver. This reads SwadgePass data from NVS to SPIRAM so that each reception doesn't require a bunch of NVS reads.
 
void deinitSwadgePassReceiver (void)
 Deinitialize the SwadgePass receiver. This frees memory.
 
void fillSwadgePassPacket (swadgePassPacket_t *packet)
 Fill a SwadgePass packet with data from all modes before transmission.
 
void sendSwadgePass (swadgePassPacket_t *packet)
 Transmit a SwadgePass packet.
 
void receiveSwadgePass (const esp_now_recv_info_t *esp_now_info, const uint8_t *data, uint8_t len, int8_t rssi)
 Receive an ESP NOW packet and save it if it is a SwadgePass packet.
 
void getSwadgePasses (list_t *swadgePasses, const struct swadgeMode *mode, bool getUsed)
 Fill a list with SwadgePass data. The list should be empty before calling this function.
 
void freeSwadgePasses (list_t *swadgePasses)
 Free SwadgePass data loaded with getSwadgePasses()
 
bool isPacketUsedByMode (swadgePassData_t *data, const struct swadgeMode *mode)
 Return if a given mode has used this SwadgePass data yet.
 
void setPacketUsedByMode (swadgePassData_t *data, const struct swadgeMode *mode, bool isUsed)
 Set if a given mode has used this SwadgePass data yet.
 

Data Structure Documentation

◆ swadgePassPacket

struct swadgePassPacket
Data Fields
uint16_t preamble Two bytes that specifically begin a SwadgePass packet.
uint8_t version A version byte to differentiate packets per-year.
int32_t username The username of the swadge owner.
struct swadgePassPacket.swadgeIt swadgeIt
struct swadgePassPacket.roboRunner roboRunner

◆ swadgePassNvs_t

struct swadgePassNvs_t
Data Fields
uint32_t usedModeMask A bitmask indicating if a mode has used this data.
swadgePassPacket_t packet The received SwadgePass packet.

◆ swadgePassData_t

struct swadgePassData_t
Data Fields
char key[NVS_KEY_NAME_MAX_SIZE] A string representation of the other Swadge's MAC address.
swadgePassNvs_t data The SwadgePass data stored in this Swadge's NVS.

◆ swadgePassPacket.swadgeIt

struct swadgePassPacket.swadgeIt
Data Fields
int8_t reactHs
int8_t memHs

◆ swadgePassPacket.roboRunner

struct swadgePassPacket.roboRunner
Data Fields
uint16_t highScore

Typedef Documentation

◆ swadgePassPacket_t

A SwadgePass packet which is transmitted over ESP NOW.

Function Documentation

◆ initSwadgePassReceiver()

void initSwadgePassReceiver ( void )

Initialize the SwadgePass receiver. This reads SwadgePass data from NVS to SPIRAM so that each reception doesn't require a bunch of NVS reads.

◆ deinitSwadgePassReceiver()

void deinitSwadgePassReceiver ( void )

Deinitialize the SwadgePass receiver. This frees memory.

◆ fillSwadgePassPacket()

void fillSwadgePassPacket ( swadgePassPacket_t * packet)

Fill a SwadgePass packet with data from all modes before transmission.

Parameters
packetThe packet to fill

◆ sendSwadgePass()

void sendSwadgePass ( swadgePassPacket_t * packet)
inline

Transmit a SwadgePass packet.

Parameters
packetThe packet to transmit

◆ receiveSwadgePass()

void receiveSwadgePass ( const esp_now_recv_info_t * esp_now_info,
const uint8_t * data,
uint8_t len,
int8_t rssi )

Receive an ESP NOW packet and save it if it is a SwadgePass packet.

This limits the number of received SwadgePasses to MAX_NUM_SWADGE_PASSES. If a SwadgePass is received while at capacity, the most used SwadgePass will be deleted first, as determined by the most number of bits set in swadgePassNvs_t.usedModeMask.

If a SwadgePass is received from a Swadge for which there already is data, the old data will be overwritten if it's different and the swadgePassNvs_t.usedModeMask will always be cleared.

Parameters
esp_now_infoMetadata for the packet, including src and dst MAC addresses
dataThe received data
lenThe length of the received data
rssiunused

◆ getSwadgePasses()

void getSwadgePasses ( list_t * swadgePasses,
const struct swadgeMode * mode,
bool getUsed )

Fill a list with SwadgePass data. The list should be empty before calling this function.

Parameters
swadgePassesA list to fill with type swadgePassData_t
modeThe Swadge Mode getting SwadgePass data (may be NULL)
getUsedtrue to return all SwadgePass data, false to return only unused SwadgePass data

◆ freeSwadgePasses()

void freeSwadgePasses ( list_t * swadgePasses)

Free SwadgePass data loaded with getSwadgePasses()

Parameters
swadgePassesA list of SwadgePasses to free. The list should contain swadgePassData_t

◆ isPacketUsedByMode()

bool isPacketUsedByMode ( swadgePassData_t * data,
const struct swadgeMode * mode )

Return if a given mode has used this SwadgePass data yet.

Parameters
dataThe SwadgePass data
modeThe mode using the SwadgePass data
Returns
true if this data has been used by the given mode yet, false if it has not

◆ setPacketUsedByMode()

void setPacketUsedByMode ( swadgePassData_t * data,
const struct swadgeMode * mode,
bool isUsed )

Set if a given mode has used this SwadgePass data yet.

This will write changes to NVS.

Parameters
dataThe SwadgePass data
modeThe mode using the SwadgePass data
isUsedtrue if the data should be set as used, false if it should be set as unused