/*#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include "image.h"*/

#define     _S8_          0x00
#define     _S16_         0x01
#define     _S32_         0x03
#define     _FLOAT_       (0x07 | 0x08)
#define     _SIGN_        0x08

struct VF {
  void *pfl;
  
};

struct VI {
  void *pvi;
  
};


float val(VF &vf) {
  return  *(float*)vf.pfl;
}
int val(VI &vi) {
  return *(int*)vi.pvi;
}


struct Type {
  uint8_t type;
};

struct I8data {
  Type dt;
  int8_t &data;
};

struct UDt {
  Type dt;
  union {
    int8_t  *i8;
    int16_t *i16;
    int32_t *i32;
    float   *f;
  };
};

struct Fdata {
  Type dt;
  float &data;
};
float f0 = 20.5;
Fdata fdata = { 2 , f0};
int8_t i80 = 15;
I8data i8data = { 1, i80 };

class AbsData {
  public:
  AbsData() {}
  virtual int data() = 0;
  //virtual float fdata() = 0;
};

class Data {
  public:
  
  Data (int8_t &data) { 
    typeData = i8_type;
    i8 = &data; 
  }
  Data (float &data) { 
    typeData = f_type;
    f = &data; 
  }
  void inc() {
    if (typeData == f_type) {
        *f += 0.1;
    } else if (typeData == i8_type) {
        *i8 += 1;
    }
  }

  void dec() {
    if (typeData == f_type) {
        *f -= 0.1;
    } else if (typeData == i8_type) {
        *i8 -= 1;
    }
  }

  void setValue(float v) {
    if (typeData == f_type) {
        *f = v;
    }
  }
  void setValue(int8_t v) {
    if (typeData == i8_type) {
        *i8 = v;
    }
  }

  void setRef(float &ref) {
    typeData = f_type;
    f = &ref; 
  }

  void setRef(int8_t &ref) {
    typeData = i8_type;
    i8 = &ref; 
  }
  /*void getValue(float &ref) {
    ref = *f;
  }*/
  /*void getValue(int8_t &ref) {
    ref = *i8;
  }*/
  auto getValue() {
    if (typeData == i8_type) {
      //decltype(int8_t);
      return (int8_t)*i8;
    }
    /*else if (typeData == f_type)
      return (float)*f;*/
    return r;
  }
    
  private:
  const signed char r = 0;
  enum {
    no_type,
    i8_type,
    i16_type,
    i32_type,
    f_type
  } typeData;
  union {
    
    int8_t  *i8;
    int16_t *i16;
    int32_t *i32;
    float   *f;
  };
};
int8_t i8param = 33;
float fparam = 33.3;
Data data(fparam);

void test_struct_Type() {
  Type *dt = (Type*)&fdata;
  Serial.println(dt->type);
}

void test_Data() {
  data.inc();
  Serial.print("fparam: " );
  Serial.println(fparam);
  Serial.println("data.setValue(34.8f);");
  data.setValue(34.8f);
  Serial.print("fparam: " );
  Serial.println(fparam);
  Serial.print("data.dec();" );
  data.dec();
  Serial.print("fparam: " );
  Serial.println(fparam);
  Serial.println("data.setRef(i8param);" );
  data.setRef(i8param);
  data.setValue((int8_t)40);
  Serial.print("i8param: " );
  Serial.println(i8param);
  auto v = data.getValue();

  

}

template <typename T>
T&& get(T&& p) {
  return p;
  //Serial.println(p);
}

template <typename T>
void inc(T& p, T&& inc) {
  p += inc;
  //Serial.println(p);
}
template <typename T>
class Param {
  public:
  Param(T& v, T l, T h, T s ) {
    counter = &v;
    low = l;
    high = h;
    step = s;
  }
  void dec() { (*counter) -= step; }
  private:
  
  T *counter;
  T low;  // valore minimo
  T high; // valore massimo consentito
  T step;  // di quanto incrementa/decrementa counter 
};

template <typename T>
class GCounter {
  public:
  GCounter(T v, T l, T h, T s ) {
    counter = v;
    low = l;
    high = h;
    step = s;
    
  }
  private:
  
  T counter;
  T low;  // valore minimo
  T high; // valore massimo consentito
  T step;  // di quanto incrementa/decrementa counter 
};
//extern const uint16_t img[];
//extern const uint16_t imgByteSize;
/*#define TFT_DC 20
#define TFT_CS 17
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
*/

void printOneShot(const char *s) {
  static char *os = nullptr;
  if (os != s) {
    Serial.println(s);
    os = const_cast<char *>(s);
  }
}
template <class T>
const uint16_t type_flag(T& x) {
  uint16_t flag = 0x8000;
  if constexpr (std::is_same_v<T, float>) {
    flag = 15;
  }
  if constexpr (std::is_same_v<T, int32_t>) {
    flag = 11;
  }
  if constexpr (std::is_same_v<T, int16_t>) {
    flag = 9;
  }
  if constexpr (std::is_same_v<T, int8_t>) {
    flag = 8;
  }

  if constexpr (std::is_same_v<T, uint32_t>) {
    flag = 3;
  }
  if constexpr (std::is_same_v<T, uint16_t>) {
    flag = 1;
  }
  if constexpr (std::is_same_v<T, uint8_t>) {
    flag = 0;
  }

  
 
  return flag; 
} 

void print_type(uint16_t flag) {
  // sarebbe utile avere qui accesso al nome
  // della variabile senza doverla passare
  // come argomento char *s, cioè dedurla tramite
  // template.
}

void setup() {
  //const uint16_t *img = get_img();
	Serial.begin(115200);
	delay(500);
	//Serial.println(imgByteSize);
  Serial.println("Ok");
  float p = 25.2;
  //print(25.2);
  inc(p, -0.1f);
  Serial.println(p);
  int h = 25;
  inc(h, -1);
  Serial.println(h);
  //tft.begin();
  //tft.setRotation(3);
  //tft.drawRGBBitmap(50, 50, img, IMG_WxH);
  // auto deduzione dei tipi funziona
  // quindi usa C++14 o maggiore
  GCounter gcounter(-63.0, -63.0, 0.0, 0.5);
  float volume = -63;
  Param param(volume, -63.0f, 0.0f, 0.5f);
  param.dec();
  Serial.println(volume);
  //test_Data();

  test_struct_Type();
  /*tft.setTextWrap(false);
  tft.setRotation(3);

  tft.setCursor(303, 0);
  tft.setTextColor(ILI9341_RED);
  tft.setTextSize(3);
  //tft.println("Hello, TFT");
  tft.println("H");

  tft.setCursor(20, 160);
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(2);
  tft.println("I can has colors?");*/
  float xtype;
  int32_t i32type;
  int16_t i16type;
  int8_t i8type;
  uint32_t u32type;
  uint16_t u16type;
  uint8_t u8type;
  //Serial.println(type_flag(xtype));
  if (type_flag(xtype) == 15) {
    Serial.println("xtype is float");
  }
   
  if (type_flag(u32type) == 3) {
    Serial.println("u32type is uint32_t");
  }
  if (type_flag(u16type) == 1) {
    Serial.println("u16type is uint16_t");
  }
  if (type_flag(u8type) == 0) {
    Serial.println("u8type is uint8_t");
  }
  if (type_flag(i32type) == 11) {
    Serial.println("i32type is int32_t");
  }
  if (type_flag(i16type) == 9) {
    Serial.println("i16type is int16_t");
  }
  if (type_flag(i8type) == 8) {
    Serial.println("i8type is int8_t");
  }
  if (type_flag(param) == 0x8000) {
    Serial.println("param is not know type");
  }
  //bool r = std::is_same<float, float>::value;
  //Serial.println(r);
}

void loop() { 
  /*printOneShot("Ciao,");
  printOneShot("questa è");*/
  //printOneShot("questa è");


  delay(1);
}
BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT