/**
 * With the new POLDI chopper there is only one chopper start signal but 4 equivalent 
 * quadrants on the chopper. This leads to the fact that the same pattern is repeated 
 * four times throughout the time intervall. This code now folds this onto one again.
 * Yet another case where a shortcoming of the HW has to be resolved in software. 
 *
 * copyright: see file COPYRIGHT
 *
 * Mark Koennecke, April 2014
 */
#include <sics.h>
#include <sicshipadaba.h>
#include <stptok.h>

static int PoldiFold (pSConnection pCon, pSicsInterp pInter, void
                           *pData, int argc, char *argv[])
{
  pHdb source, target, dim;
  int *sourceData, *targetData, *sourceCurrent, *targetCurrent;
  unsigned int nDet, nTof, nSourceTof;
  int offset[4], i, j, k;
  char num[20], *pPtr;

  if(argc < 4) {
    SCWrite(pCon,"ERROR: not enough arguments to poldifold",eError);
    return 0;
  }

  /*
    reading and checking arguments
  */
  source = FindHdbNode(NULL,argv[1],pCon);
  target = FindHdbNode(NULL,argv[2],pCon);
  if(source == NULL || target == NULL){
    SCPrintf(pCon,eError,"ERROR: source %s or target %s path invalid",
	     argv[1], argv[2]);
    return 0;
  }
  pPtr = argv[3];
  for(i = 0; i < 4; i++){
    pPtr = stptok(pPtr,num,sizeof(num),",");
    if(pPtr == NULL){
      SCWrite(pCon,"ERROR: not enough values in the offset list",eError);
      return 0;
    }
    offset[i] = atoi(num);
  }
  pPtr = stptok(pPtr,num,sizeof(num),",");
  if(pPtr == NULL){
      SCWrite(pCon,"ERROR: not enough values in the offset list",eError);
      return 0;
  }
  nTof = atoi(num);

  dim = GetHipadabaNode(source->mama,"dim");
  if(dim == NULL){
    SCPrintf(pCon,eError,"ERROR: failed to find dimensions beneath %s, no HM?", 
	     argv[1]);
    return 0;
  }
  nDet = dim->value.v.intArray[0];  
  nSourceTof = dim->value.v.intArray[1];

  /*
    check for badly initailized data array 
  */
  if(source->value.arrayLength < nDet*nSourceTof){
    SCWrite(pCon,"ERROR: hm data not initialised to correct length!", eError);
    return 0;
  }

  /*
    ensure enough space to write
  */
  if(target->value.arrayLength != nDet*nTof){
    free(target->value.v.intArray);
    target->value.v.intArray = malloc(nDet*nTof*sizeof(int));
    if(target->value.v.intArray == NULL){
      SCWrite(pCon,"ERROR: out of memory in poldifold",eError);
      return 0;
    }
    target->value.arrayLength = nDet*nTof;
  }
  sourceData = source->value.v.intArray;
  targetData = target->value.v.intArray;
  memset(targetData,0,nDet*nTof*sizeof(int));

  for(i = 0; i < nDet; i++){
    sourceCurrent = sourceData + i*nSourceTof;
    targetCurrent = targetData + i*nTof;
    for(j = 0; j < 4; j++){
      for(k = 0; k < nTof; k++){
	targetCurrent[k] += sourceCurrent[offset[j] + k]; 
      }
    }
  }
  NotifyHipadabaPar(target,pCon);
  SCSendOK(pCon);
  return 1;
}
/*-----------------------------------------------------------------*/
int MakePoldiFold (pSConnection pCon, pSicsInterp pInter, void
                           *pData, int argc, char *argv[])
{
    AddCommand(pInter, "poldifold", PoldiFold, NULL, NULL);
    return 1;
}
