Mozzi  version v2.0
sound synthesis library for Arduino
mozzi_pgmspace.h
1 /*
2  * mozzi_pgmspace.h
3  *
4  * This file is part of Mozzi.
5  *
6  * Copyright 2018-2024 Thomas Friedrichsmeier and the Mozzi Team
7  *
8  * Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.
9  *
10  */
11 
12 #ifndef MOZZI_PGMSPACE_H
13 #define MOZZI_PGMSPACE_H
14 
15 /* Cross-platform wrapper around avr/pgmspace.h, i.e. macros and functions to
16 * store data in and retrieve data from flash memory. */
17 
18 #include "hardware_defines.h"
19 
20 #if IS_ESP8266() || IS_ESP32() || IS_RP2040() || IS_RENESAS()
21 template<typename T> inline T FLASH_OR_RAM_READ(T* address) {
22  return (T) (*address);
23 }
24 #define CONSTTABLE_STORAGE(X) const X
25 #else
26 #include <avr/pgmspace.h>
27 // work around missing std::is_const
28 template<typename T> inline bool mozzi_is_const_pointer(T*) { return false; }
29 template<typename T> inline bool mozzi_is_const_pointer(const T*) { return true; }
32 template<typename T> inline T mozzi_pgm_read_wrapper(const T* address) {
33  static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Data type not supported");
34  switch (sizeof(T)) {
35  case 1: return (T) pgm_read_byte_near(address);
36  case 2: return (T) pgm_read_word_near(address);
37  case 4: return (T) pgm_read_dword_near(address);
38  }
39  // 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?
40  return (T) (pgm_read_dword_near(address) | (uint64_t) pgm_read_dword_near(((byte*) address) + 4) << 32);
41 }
42 template<> inline float mozzi_pgm_read_wrapper(const float* address) {
43  return pgm_read_float_near(address);
44 }
45 template<> inline double mozzi_pgm_read_wrapper(const double* address) {
46  static_assert(sizeof(uint64_t) == sizeof(double) || sizeof(float) == sizeof(double), "Reading double from pgmspace memory not supported on this architecture");
47  if (sizeof(double) == sizeof(uint64_t)) {
48  union u { uint64_t i; double d; };
49  return u{mozzi_pgm_read_wrapper((uint64_t*) address)}.d;
50  }
51  return pgm_read_float_near(address);
52 }
57 template<typename T> inline T FLASH_OR_RAM_READ(T* address) {
58  if(mozzi_is_const_pointer(address)) {
59  return mozzi_pgm_read_wrapper(address);
60  }
61  return (T) *address;
62 }
67 #define CONSTTABLE_STORAGE(X) const X __attribute__((section(".progmem.data")))
68 #endif
69 
70 #endif
T FLASH_OR_RAM_READ(T *address)
Read a value from flash or RAM.
T mozzi_pgm_read_wrapper(const T *address)
Helper function to FLASH_OR_RAM_READ().