Added HTTP-API support, Standalone AP Support and Built-in Melodies
This commit is contained in:
253
vesper/src/BuiltInMelodies/BuiltInMelodies.hpp
Normal file
253
vesper/src/BuiltInMelodies/BuiltInMelodies.hpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* ═══════════════════════════════════════════════════════════════════════════════════
|
||||
* BUILTINMELODIES.HPP - Firmware-Baked Melody Library
|
||||
* ═══════════════════════════════════════════════════════════════════════════════════
|
||||
*
|
||||
* 🎵 BUILT-IN MELODY LIBRARY FOR VESPER 🎵
|
||||
*
|
||||
* This file contains melodies baked directly into the firmware, eliminating
|
||||
* the need for SD card downloads. Each melody is stored in PROGMEM to save RAM.
|
||||
*
|
||||
* 🏗️ ARCHITECTURE:
|
||||
* • Melodies stored in PROGMEM (Flash memory, not RAM)
|
||||
* • Each melody step is 2 bytes (uint16_t bitmask)
|
||||
* • Metadata includes name, UID, default speed
|
||||
* • Easy to add new melodies
|
||||
*
|
||||
* 📦 STORAGE EFFICIENCY:
|
||||
* • Small melodies (~30 steps = 60 bytes)
|
||||
* • Large melodies (~200 steps = 400 bytes)
|
||||
* • 40 melodies average = ~6-10KB total (Flash, not RAM!)
|
||||
*
|
||||
* 🎶 MELODY FORMAT:
|
||||
* Each uint16_t is a bitmask:
|
||||
* - Bit 0-15: Which bells/notes to activate
|
||||
* - Example: 0x0001 = Bell 0, 0x0003 = Bells 0+1, 0x8000 = Bell 15
|
||||
*
|
||||
* 📋 VERSION: 1.0
|
||||
* 📅 DATE: 2025-12-28
|
||||
* 👨💻 AUTHOR: Advanced Bell Systems
|
||||
* ═══════════════════════════════════════════════════════════════════════════════════
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <vector>
|
||||
#include <pgmspace.h>
|
||||
|
||||
namespace BuiltInMelodies {
|
||||
|
||||
// ═════════════════════════════════════════════════════════════════════════════════
|
||||
// MELODY METADATA STRUCTURE
|
||||
// ═════════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
struct MelodyInfo {
|
||||
const char* name; // Display name
|
||||
const char* uid; // Unique identifier
|
||||
const uint16_t* data; // Pointer to melody data in PROGMEM
|
||||
uint16_t stepCount; // Number of steps
|
||||
uint16_t defaultSpeed; // Default speed in milliseconds per beat
|
||||
};
|
||||
|
||||
// ═════════════════════════════════════════════════════════════════════════════════
|
||||
// EXAMPLE MELODIES - Add your melodies here!
|
||||
// ═════════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
// Example: Simple Scale (C-D-E-F-G-A-B-C)
|
||||
const uint16_t PROGMEM melody_simple_scale[] = {
|
||||
0x0001, 0x0002, 0x0004, 0x0008,
|
||||
0x0010, 0x0020, 0x0040, 0x0080
|
||||
};
|
||||
|
||||
// Example: Happy Birthday (simplified)
|
||||
const uint16_t PROGMEM melody_happy_birthday[] = {
|
||||
0x0001, 0x0001, 0x0002, 0x0001,
|
||||
0x0008, 0x0004, 0x0001, 0x0001,
|
||||
0x0002, 0x0001, 0x0010, 0x0008,
|
||||
0x0001, 0x0001, 0x0080, 0x0008,
|
||||
0x0004, 0x0002, 0x0040, 0x0040,
|
||||
0x0008, 0x0004, 0x0002
|
||||
};
|
||||
|
||||
// Example: Jingle Bells (simplified)
|
||||
const uint16_t PROGMEM melody_jingle_bells[] = {
|
||||
0x0004, 0x0004, 0x0004, 0x0000,
|
||||
0x0004, 0x0004, 0x0004, 0x0000,
|
||||
0x0004, 0x0008, 0x0001, 0x0002,
|
||||
0x0004, 0x0000, 0x0000, 0x0000,
|
||||
0x0008, 0x0008, 0x0008, 0x0008,
|
||||
0x0008, 0x0004, 0x0004, 0x0004,
|
||||
0x0002, 0x0002, 0x0004, 0x0002,
|
||||
0x0008, 0x0000, 0x0000, 0x0000
|
||||
};
|
||||
|
||||
// Example: Westminster Chimes
|
||||
const uint16_t PROGMEM melody_westminster_chimes[] = {
|
||||
0x0008, 0x0004, 0x0002, 0x0001,
|
||||
0x0001, 0x0002, 0x0008, 0x0004,
|
||||
0x0008, 0x0001, 0x0002, 0x0004,
|
||||
0x0002, 0x0008, 0x0004, 0x0001
|
||||
};
|
||||
|
||||
// Example: Alarm Pattern
|
||||
const uint16_t PROGMEM melody_alarm[] = {
|
||||
0x0001, 0x0080, 0x0001, 0x0080,
|
||||
0x0001, 0x0080, 0x0001, 0x0080,
|
||||
0x0000, 0x0000, 0x0001, 0x0080,
|
||||
0x0001, 0x0080, 0x0001, 0x0080
|
||||
};
|
||||
|
||||
// Example: Doorbell
|
||||
const uint16_t PROGMEM melody_doorbell[] = {
|
||||
0x0004, 0x0008, 0x0004, 0x0008
|
||||
};
|
||||
|
||||
// Example: Single Bell Test
|
||||
const uint16_t PROGMEM melody_single_bell[] = {
|
||||
0x0001
|
||||
};
|
||||
|
||||
// ═════════════════════════════════════════════════════════════════════════════════
|
||||
// MELODY LIBRARY - Array of all built-in melodies
|
||||
// ═════════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
const MelodyInfo MELODY_LIBRARY[] = {
|
||||
{
|
||||
"Simple Scale",
|
||||
"builtin_scale",
|
||||
melody_simple_scale,
|
||||
sizeof(melody_simple_scale) / sizeof(uint16_t),
|
||||
200 // 200ms per beat
|
||||
},
|
||||
{
|
||||
"Happy Birthday",
|
||||
"builtin_happy_birthday",
|
||||
melody_happy_birthday,
|
||||
sizeof(melody_happy_birthday) / sizeof(uint16_t),
|
||||
250
|
||||
},
|
||||
{
|
||||
"Jingle Bells",
|
||||
"builtin_jingle_bells",
|
||||
melody_jingle_bells,
|
||||
sizeof(melody_jingle_bells) / sizeof(uint16_t),
|
||||
180
|
||||
},
|
||||
{
|
||||
"Westminster Chimes",
|
||||
"builtin_westminster",
|
||||
melody_westminster_chimes,
|
||||
sizeof(melody_westminster_chimes) / sizeof(uint16_t),
|
||||
400
|
||||
},
|
||||
{
|
||||
"Alarm",
|
||||
"builtin_alarm",
|
||||
melody_alarm,
|
||||
sizeof(melody_alarm) / sizeof(uint16_t),
|
||||
150
|
||||
},
|
||||
{
|
||||
"Doorbell",
|
||||
"builtin_doorbell",
|
||||
melody_doorbell,
|
||||
sizeof(melody_doorbell) / sizeof(uint16_t),
|
||||
300
|
||||
},
|
||||
{
|
||||
"Single Bell Test",
|
||||
"builtin_single_bell",
|
||||
melody_single_bell,
|
||||
sizeof(melody_single_bell) / sizeof(uint16_t),
|
||||
100
|
||||
}
|
||||
};
|
||||
|
||||
const uint16_t MELODY_COUNT = sizeof(MELODY_LIBRARY) / sizeof(MelodyInfo);
|
||||
|
||||
// ═════════════════════════════════════════════════════════════════════════════════
|
||||
// HELPER FUNCTIONS
|
||||
// ═════════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* @brief Check if a UID is a built-in melody
|
||||
* @param uid The melody UID to check
|
||||
* @return true if it's a built-in melody (starts with "builtin_")
|
||||
*/
|
||||
inline bool isBuiltInMelody(const String& uid) {
|
||||
return uid.startsWith("builtin_");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find a built-in melody by UID
|
||||
* @param uid The melody UID to find
|
||||
* @return Pointer to MelodyInfo if found, nullptr otherwise
|
||||
*/
|
||||
inline const MelodyInfo* findMelodyByUID(const String& uid) {
|
||||
for (uint16_t i = 0; i < MELODY_COUNT; i++) {
|
||||
if (uid == MELODY_LIBRARY[i].uid) {
|
||||
return &MELODY_LIBRARY[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load a built-in melody into a vector
|
||||
* @param uid The melody UID to load
|
||||
* @param melodySteps Vector to fill with melody data
|
||||
* @return true if melody was found and loaded, false otherwise
|
||||
*/
|
||||
inline bool loadBuiltInMelody(const String& uid, std::vector<uint16_t>& melodySteps) {
|
||||
const MelodyInfo* melody = findMelodyByUID(uid);
|
||||
if (!melody) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resize vector and copy data from PROGMEM
|
||||
melodySteps.resize(melody->stepCount);
|
||||
for (uint16_t i = 0; i < melody->stepCount; i++) {
|
||||
melodySteps[i] = pgm_read_word(&(melody->data[i]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get list of all built-in melodies as JSON string
|
||||
* @return JSON array string of melody names and UIDs
|
||||
*/
|
||||
inline String getBuiltInMelodiesJSON() {
|
||||
String json = "[";
|
||||
for (uint16_t i = 0; i < MELODY_COUNT; i++) {
|
||||
if (i > 0) json += ",";
|
||||
json += "{";
|
||||
json += "\"name\":\"" + String(MELODY_LIBRARY[i].name) + "\",";
|
||||
json += "\"uid\":\"" + String(MELODY_LIBRARY[i].uid) + "\",";
|
||||
json += "\"steps\":" + String(MELODY_LIBRARY[i].stepCount) + ",";
|
||||
json += "\"speed\":" + String(MELODY_LIBRARY[i].defaultSpeed);
|
||||
json += "}";
|
||||
}
|
||||
json += "]";
|
||||
return json;
|
||||
}
|
||||
|
||||
} // namespace BuiltInMelodies
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════
|
||||
// USAGE EXAMPLE:
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════
|
||||
/*
|
||||
// Check if melody is built-in
|
||||
if (BuiltInMelodies::isBuiltInMelody(uid)) {
|
||||
// Load it from firmware
|
||||
std::vector<uint16_t> melodyData;
|
||||
if (BuiltInMelodies::loadBuiltInMelody(uid, melodyData)) {
|
||||
// Use melodyData...
|
||||
}
|
||||
} else {
|
||||
// Load from SD card as usual
|
||||
}
|
||||
*/
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════
|
||||
Reference in New Issue
Block a user