| Mozzi version v1.1.0 sound synthesis library for Arduino |

mozzi_pgmspace.h
1 #ifndef MOZZI_PGMSPACE_H
2 #define MOZZI_PGMSPACE_H
3
4 /* Cross-platform wrapper around avr/pgmspace.h, i.e. macros and functions to
5 * store data in and retrieve data from flash memory. */
6
7 #include "hardware_defines.h"
8
9 #if IS_ESP8266() || IS_ESP32()
10 template<typename T> inline T FLASH_OR_RAM_READ(T* address) {
11 return (T) (*address);
12 }
13 #define CONSTTABLE_STORAGE(X) const X
14 #else
15 #include <avr/pgmspace.h>
16 // work around missing std::is_const
17 template<typename T> inline bool mozzi_is_const_pointer(T* x) { return false; }
18 template<typename T> inline bool mozzi_is_const_pointer(const T* x) { return true; }
19 /** @ingroup core
20 * Helper function to FLASH_OR_RAM_READ(). You do not want to call this, directly. */
21 template<typename T> inline T mozzi_pgm_read_wrapper(const T* address) {
22 static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Data type not supported");
23 switch (sizeof(T)) {
24 case 1: return (T) pgm_read_byte_near(address);
25 case 2: return (T) pgm_read_word_near(address);
26 case 4: return (T) pgm_read_dword_near(address);
27 }
28 // case 8: AVR-libc does not provide a read function for this, so we combine two 32-bit reads. TODO: is this MSB/LSB safe?
29 return (T) (pgm_read_dword_near(address) | (uint64_t) pgm_read_dword_near(((byte*) address) + 4) << 32);
30 }
31 template<> inline float mozzi_pgm_read_wrapper(const float* address) {
32 return pgm_read_float_near(address);
33 }
34 template<> inline double mozzi_pgm_read_wrapper(const double* address) {
35 static_assert(sizeof(uint64_t) == sizeof(double) || sizeof(float) == sizeof(double), "Reading double from pgmspace memory not supported on this architecture");
36 if (sizeof(double) == sizeof(uint64_t)) {
37 union u { uint64_t i; double d; };
38 return u{mozzi_pgm_read_wrapper((uint64_t*) address)}.d;
39 }
40 return pgm_read_float_near(address);
41 }
42 /** @ingroup core
43 * Read a value from flash or RAM. The specified address is read from flash, if T is const, _and_ const
44 * tables are stored in flash on this platform (i.e. not on ESP8266). It is read from RAM, if T is not-const
45 * or tables are always stored in RAM on this platform. @see CONSTTABLE_STORAGE . */
46 template<typename T> inline T FLASH_OR_RAM_READ(T* address) {
47 if(mozzi_is_const_pointer(address)) {
48 return mozzi_pgm_read_wrapper(address);
49 }
50 return (T) *address;
51 }
52 /** @ingroup core
53 * Declare a variable such that it will be stored in flash memory, instead of RAM, on platforms where this
54 * is reasonably possible (i.e. not on ESP8266, where random location flash memory access is too slow).
55 * To read the variable in a cross-platform compatible way, use FLASH_OR_RAM_READ(). */
56 #define CONSTTABLE_STORAGE(X) const X __attribute__((section(".progmem.data")))
57 #endif
58
59 #endif
IS_ESP8266
#define IS_ESP8266()
Definition: hardware_defines.h:19
IS_ESP32
#define IS_ESP32()
Definition: hardware_defines.h:20