
/**
 *
 * Modul RMS-Bildner
 * 
 * MalZeit 06/2014
 *
 */

#include <rms_bildner.h>

#include <math.h>

#include <ad_wandler.h>

volatile uint32_t gSumme = 0;
volatile uint8_t gZaehler = 0;

void RmsBildnerInit(void);
void RmsBildnerStart(void);
void RmsBildnerCallback(uint16_t analog);

uint16_t RmsBilden(void);
void RmsHoleAtomic(uint32_t *pSumme, uint8_t *pZaehler);
 
/**
 * 
 * Initialisiere Modul RMS-Bildner
 * 
 */

void RmsBildnerInit(void)
{
  AdWandlerInit();
  AdWandlerRegistriereCb(RmsBildnerCallback);
}

/**
 * 
 * Bildet arithmetischen Mittelwert aus den einzelnen RMS-Werten
 * ATTENTION: Lange Bearbeitungzeit!
 * ATTENTION: Enthält atomaren Abschnitt gegenüber AD-Wandler
 * 
 */

uint16_t RmsBilden(void)
{
  uint32_t Summe;
  uint8_t Zaehler;
  uint16_t ret;
  AD_WANDLER_START_ATOMIC;
  RmsHoleAtomic(&Summe, &Zaehler);
  AD_WANDLER_STOP_ATOMIC;
  
  if (Summe != 0) {
    ret = sqrt(Summe/Zaehler);
  } else {
    ret = 0;
  }
  
  return ret<<6; // 10-Bit zu 16-Bit Vollausschlag
}

/**
 * 
 * Abgesetzer Zugriff auf globale Variablen als Optimierungszaun bei atomaren Operationen
 * 
 */

void RmsHoleAtomic(uint32_t *pSumme, uint8_t *pZaehler)
{
  *pSumme = gSumme;
  *pZaehler = gZaehler;
  gSumme = 0;
  gZaehler = 0;
}

/**
 * 
 * 
 * 
 */

void RmsBildnerStart(void)
{
  AdWandlerStart();  
}

/**
 * 
 * Callback-Funktion für 10-Bit AD-Wandler
 * Bildet akkumulierte Summe für bis zu 64 (2^6) Werte
 * 
 */

void RmsBildnerCallback(uint16_t analog)
{
  if (gSumme <= (0xffffffff - 0x000fffff) && gZaehler < 255 ) { // kein Überlauf zu erwarten bei 10-Bit AD-Wandler
    gSumme += (uint32_t) analog * (uint32_t) analog;
    gZaehler += 1;
  } else {
    // TODO Hier passiert ein Fehler (oder erstmal nix) Reset??
  }
}

// EOF 
