
/* MalZeit 07/2014 */

#include <dmx_steuerung.h>

#include <util/atomic.h>

#include "logarithmierer.h"
#include "dmx_uart.h"

#define DMX_PUFFER_GROESSE 128

struct DmxPuffer {
  uint8_t Daten[DMX_PUFFER_GROESSE];
  uint8_t Zaehler;
};

#define STUFEN_ZAHL 16
#define BEREICH_DB -24

static uint16_t gStufen[STUFEN_ZAHL] = {0};


volatile struct DmxPuffer gDmxPuffer = {{0}, 0};

void DmxSteuerungInit(void);
void DmxSteuerungStart(void);

void DmxSteuerungCallback(void);


void DmxSteuerungSetzeWert(uint16_t wert);


/**
 * 
 * 
 * 
 */
void DmxSteuerungInit(void)
{
  DmxUartInit();
  DmxUartRegistriereCb(&DmxSteuerungCallback);
  LogarithmiererErzeugeSkala(gStufen, STUFEN_ZAHL, BEREICH_DB);

}

/**
 * 
 * 
 * 
 */
void DmxSteuerungStart(void)
{
  DmxUartStart();
}


/**
 * 
 * 
 * 
 */
void DmxSteuerungCallback(void)
{  
  uint8_t zaehler = gDmxPuffer.Zaehler; // volatile puffern
  gDmxPuffer.Zaehler += 1;
  // 3x mit Geloescht
  // 1x mit Gesetzt
  if(zaehler < 1) {
    DmxUartTxBreak();
  } else if(zaehler < 2) {
    DmxUartTxData(0); // Null übertragen
  } else if(zaehler < (DMX_PUFFER_GROESSE+2)){
    DmxUartTxData(gDmxPuffer.Daten[zaehler-2]);
  } else {
    // Interrupt löscht sich selbst.
  }
}

/**
 * 
 * 
 * TODO Überlappung??
 */
void DmxSteuerungSetzeWert(uint16_t wert)
{
static  uint16_t vorWert = 0;
  uint8_t anzeige;
  uint8_t i = 0;
  // stoppe DRE-Interruptkette
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE)  {
    gDmxPuffer.Zaehler = -1;
  }
  DmxUartWarteAufTxc();

  uint16_t temp = wert;
  wert = (vorWert/2) + (wert/2);
  vorWert = temp;
  
  anzeige = LogarithmiererBildeWert(wert, gStufen, STUFEN_ZAHL);

  // DMX PixelTube ansteuern
  
  uint8_t zaehler = anzeige;
  while(i < 3*STUFEN_ZAHL) { // In jeder Verzweigung muss i erhöht werden!
    if (zaehler != 0) {
      zaehler -= 1;
      if(i < 9*3) { // Grüner Bereich 1..10
        gDmxPuffer.Daten[i] = 0; // rot
        i += 1;
        gDmxPuffer.Daten[i] = 0xff; // grün
        i += 1;
        gDmxPuffer.Daten[i] = 0; // blau
        i += 1;
      } else if ( i < 3*13)  { // Gelber Bereich 11..13
        gDmxPuffer.Daten[i] = 0xff; // = 0xff / sqrt(2) // rot
        i += 1;
        gDmxPuffer.Daten[i] = 0x7f; // grün
        i += 1;
        gDmxPuffer.Daten[i] = 0;
        i += 1;      
      } else {
        gDmxPuffer.Daten[i] = 0xff; // rot
        i += 1;
        gDmxPuffer.Daten[i] = 0; // grün
        i += 1;
        gDmxPuffer.Daten[i] = 0; // blau
        i += 1;
      } 
    } else { // zaehler == 0 => aus
      gDmxPuffer.Daten[i] = 0;
      i += 1;
      gDmxPuffer.Daten[i] = 0;
      i += 1;
      gDmxPuffer.Daten[i] = 0;
      i += 1;
    }  
  }
  
  // DMX Dekoleuchte ansteuern in verschiedenen Farben
  // weiß, rot, grün, blau, orange, lila = 6*8 = 48
  
  // Eurolite PixelTube
  
  // Starville LED Par Spot
  // CH1 = R, CH2 = G, CH3 = B, CH4 = Macro, CH5 = Strobe, CH6 = Modus, CH7 = Dimmer
  
  // Eurolite Par 64
  // CH1 = R, CH2 = G, CH3 = B, CH4 = Dimmer, CH5 = Strobe
  
  // Farbverlauf grün nach rot
  
  for(; i < DMX_PUFFER_GROESSE; i++) {
    gDmxPuffer.Daten[i] = 0;
  }
  
  // starte DRE-Interruptkette
  gDmxPuffer.Zaehler = 0;
  DmxSteuerungCallback();
  
}
// EOF
