// ---------------------------------------------------------------------------
// CDTMFPayloadFormatWrite::StartDTMFToneL
// Starts a timer which sends specified DTMF digit periodically until 
// StopDTMFTone() is called.
// ---------------------------------------------------------------------------
//
void CDTMFPayloadFormatWrite::StartDTMFToneL( const TChar aTone )
    {
    TUint32 tickCount( User::NTickCount() );
    
    DP_DTMF_WRITE3(  _L("CDTMFPayloadFormatWrite::StartDTMFToneL aTone = %c, tick = %u"),
        static_cast<TUint>( aTone ), tickCount );
    
    DP_DTMF_WRITE2( _L("CDTMFPayloadFormatWrite::StartDTMFToneL enc state %d"),
        iStateMachine->State() );
    
    __ASSERT_ALWAYS( IsValidDigit( aTone ), User::Leave( KErrArgument ) );
    
    iSendingMode = EModeManual;
    
    TSendBufferElement element( aTone, tickCount );
    iSendBuffer.AppendL( element );
    
    if ( EStateSendingIdle == iStateMachine->State() )
        {
        if ( KSignalOutbandDtmf == iGenerationMode )
            {
            iSinkBuffer->Data().FillZ( KDTMFDefaultPayloadSize );
            }

        iStateMachine->ChangeStateTo( EStateEncodeNextDigit );
        }
    else
        {
        DP_DTMF_WRITE( 
            _L("CDTMFPayloadFormatWrite::StartDTMFToneL - REQ BUFFERED") );
        }
    }
/**
 * @function GetSelectedDigit
 * @brief return the selected digit corresponding to the x coord coming from the touchscreen
 * @param const rot_val_st *rval: pointer to rot value object
 * @param coord_t xt: x coord coming from touchscreen
 * @return uint8_t: corresponding #id of the selected digit (ensured to be a 'valid' digit).
 */
static uint8_t GetSelectedDigit(const rot_val_st *rval, coord_t xt) {

  bool done = false;
  coord_t xDigit;
  uint8_t digit = 0;

  /*loop until the current digit coord matches with xt*/
  while(done == false) {

    xDigit = GetDigitCoord(rval, digit);

    if(xt > xDigit || IsValidDigit(rval, digit + 1) == false) done = true;
    else digit++;
  }

  return digit;
}
/**
 * @function GUI_W_RotaryValueSetDotPos
 * @brief set the dot position
 * @param g_obj_st *obj: pointer to the generic object corresponding to the rot value
 * @param uint8_t posDot: dot pos
 * @return int8_t: 0 success, -1 error
 */
int8_t GUI_W_RotaryValueSetDotPos(g_obj_st /*@null@*/ *obj, uint8_t posDot) {

  int8_t res = -1;
  rot_val_st *rval = NULL;

  /*retrieve objects*/
  if(obj == NULL) obj = GUI_GetLastAddedObject();
  if(obj != NULL && obj->draw == RotValDraw) {
    rval = (rot_val_st *) obj->obj;

    /*set new range*/
    if(IsValidDigit(rval, posDot)) {
      rval->posDot = posDot;
      res = 0;
      GUI_ObjSetNeedRefresh(obj, true);
    }
  }

  return res;
}
/**
 * @function RotValDraw
 * @brief rotary value draw function
 * @param void *_g_obj: generic object
 * @param void *_obj: rot val object
 * @return none
 */
static void RotValDraw(void *_g_obj, void *_obj) {

  g_obj_st *g_obj;
  rot_val_st *rval;
  rect_st lrec, absRec;
  color_t colBack, colText, colSetText;
  uint8_t digitId, len, glyph, str[MAX_VAL_STR], typeBox = 0;
  bool bNeg;
  surfaceId_t idSurface = SURFACE_LCD;

  /*retrieve generic & specific object*/
  if(_g_obj != NULL && _obj != NULL) {
    g_obj = (g_obj_st *) _g_obj;
    rval = (rot_val_st*) _obj;

    /*try to create a double buffer in RAM*/
    absRec = g_obj->rec;
    absRec.x = 0;
    absRec.y = 0;
    idSurface = P2D_SurfaceCreate(&absRec);
    if(idSurface != SURFACE_LCD) {
      P2D_SetDest(idSurface);
    }
    else {
      absRec = g_obj->rec;
    }

    /*color selection*/
    if(GUI_ObjIsDisabled(g_obj)) {
      SetLut(G_LUT_DISABLED);
      colBack = GetColor(G_COL_E_BACKGROUND);
      colText = GetColor(G_COL_D_TEXT);
      colSetText = GetColor(G_COL_D_TEXT);
      typeBox = 2;
    }
    else if(GUI_ObjIsPressed(g_obj)) {
      SetLut(G_LUT_NORMAL);
      colBack = GetColor(G_COL_E_BACKGROUND);
      colText = rval->colorText;
      colSetText = GetColor(G_COL_SPECIAL);
    }
    else {
      SetLut(G_LUT_NORMAL);
      colBack = GetColor(G_COL_E_BACKGROUND);
      colText = rval->colorText;
      if(rval->lock != 0) colSetText = rval->colorText;
      else colSetText = GetColor(G_COL_SPECIAL);
    }

    /*P2D configuration*/
    P2D_SetDisplayMode(DISPLAY_SOLID);
    P2D_SetLineType(LINE_SOLID);
    SetFont(rval->font);

    /*background*/
    P2D_SetColors(colBack, colBack);
    lrec = absRec;
    P2D_SetColors(COLOR_LIGHT_GREY, COLOR_LIGHT_GREY);
    DrawBox(&lrec, typeBox);

    /*sprite*/
    P2D_SetDisplayMode(DISPLAY_TRANSPARENT);
    if(rval->img != 0) {
      Sprite(lrec.x + 4, lrec.y + ((int32_t)lrec.h - SpriteGetHeight(rval->img)) / 2, rval->img);
    }

    /*display the value's unit string*/
    lrec.x += 1; lrec.y += 1;
    lrec.w -= 2; lrec.h -= 2;
    P2D_SetColors(colText, colBack);
    lrec.y = absRec.y + ((coord_t)absRec.h - P2D_GetTextHeight()) / 2;
    P2D_PutText(absRec.x + rval->xUnit, lrec.y, rval->strUnit);

    /*format value*/
    (void) snprintf( (char *)str, MAX_VAL_STR, "%d", *(rval->pVar));
    len = gstrlen(str);
    bNeg = *(rval->pVar) < 0 ? true : false;

    /*display each digit, one by one, from right to left*/
    for(digitId = 0; IsValidDigit(rval, digitId) == true; digitId++) {

      /*get the x coord of the current digit*/
      lrec.x = absRec.x + GetDigitCoord(rval, digitId);

      /*special color + highlighted if the current digit is the selected one*/
      if(digitId == rval->selectedDigit && rval->lock == false) {
        P2D_SetColors(colSetText, colBack);
      }
      else {
        P2D_SetColors(colText, colBack);
      }

      /*display the snprintf content, excepting the '-'*/
      if(digitId < len) {
        glyph = str[len - digitId - 1];
        if(glyph == (uint8_t)'-') glyph = (uint8_t)'0'; /*will be displayed at end*/
      }
      /*for small value (i.e. digitId >= strlen), fill with '0'*/
      else {
        glyph = (uint8_t)'0';
      }

      P2D_PutGlyph(lrec.x, lrec.y, glyph);
    }

    /*display the sign, only if negative*/
    if(bNeg) {
      P2D_SetColors(colText, colBack);
      lrec.x = absRec.x + GetDigitCoord(rval, digitId);
      P2D_PutGlyph(lrec.x, lrec.y, (uint8_t)'-');
    }

    /*display the dot, if any*/
    if(rval->posDot > 0) {
      P2D_SetColor(colText);
      lrec.x = absRec.x + GetDigitCoord(rval, rval->posDot - 1) - rval->spacing;
      P2D_SetColors(colText, colBack);
      P2D_PutGlyph(lrec.x, lrec.y, (uint8_t) '.');
    }

    /*if the double buffer was active, flip it to the screen*/
    if(idSurface != SURFACE_LCD) {
      P2D_SetDest(SURFACE_LCD);
      P2D_CopySurface(idSurface, &absRec, &(g_obj->rec));
      P2D_SurfaceDelete(idSurface);
    }
  }
}
/**
 * @function RotValDraw
 * @brief rotary value draw function
 * @param void *_g_obj: generic object
 * @param void *_obj: rot val object
 * @return none
 */
static void RotValDraw(void *_g_obj, void *_obj) {

  g_obj_st *g_obj;
  rot_val_st *rval;
  rect_st lrec;
  color_t colBack, colLine, colText, colSetText;
  uint8_t digitId, len, glyph, str[MAX_VAL_STR];
  bool bNeg;

  /*retrieve generic & specific object*/
  if(_g_obj != NULL && _obj != NULL) {
    g_obj = (g_obj_st *) _g_obj;
    rval = (rot_val_st*) _obj;

    /*color selection*/
    if(GUI_ObjIsDisabled(g_obj)) {
      colBack = GetColor(G_COL_BACKGROUND);
      colLine = GetColor(G_COL_LOWER_REC);
      colText = GetColor(G_COL_D_TEXT);
      colSetText = rval->colorText;
    }
    else if(GUI_ObjIsPressed(g_obj)) {
      colBack = GetColor(G_COL_E_BACKGROUND);
      colLine = GetColor(G_COL_LOWER_REC);
      colText = rval->colorText;
      colSetText = GetColor(G_COL_SPECIAL);
    }
    else {
      colBack = GetColor(G_COL_E_BACKGROUND);
      colLine = GetColor(G_COL_LOWER_REC);
      colText = rval->colorText;
      if(rval->lock != 0) colSetText = rval->colorText;
      else colSetText = GetColor(G_COL_SPECIAL);
    }

    /*P2D configuration*/
    P2D_SetDisplayMode(DISPLAY_SOLID);
    P2D_SetLineType(LINE_SOLID);
    SetFont(rval->font);
    P2D_SetColors(colBack, colBack);

    /*background*/
    lrec = g_obj->rec;
    lrec.x += 1; lrec.y += 1;
    lrec.w -= 2; lrec.h -= 2;
    P2D_FillRect(&lrec);

    /*display the value's unit string*/
    P2D_SetColor(colText);
    lrec.y = g_obj->rec.y + ((coord_t)g_obj->rec.h - P2D_GetTextHeight()) / 2;
    P2D_PutText(rval->xUnit, lrec.y, rval->strUnit);

    /*format value*/
    (void) snprintf( (char *)str, MAX_VAL_STR, "%d", *(rval->pVar));
    len = gstrlen(str);
    bNeg = *(rval->pVar) < 0 ? true : false;

    /*display each digit, one by one, from right to left*/
    for(digitId = 0; IsValidDigit(rval, digitId) == true; digitId++) {

      /*get the x coord of the current digit*/
      lrec.x = GetDigitCoord(rval, digitId);

      /*special color + highlighted if the current digit is the selected one*/
      if(digitId == rval->selectedDigit && rval->lock == false) {
        P2D_SetColor(colSetText);
        lrec.h = P2D_GetTextHeight();
        lrec.w = rval->wCar;
        P2D_FillRect(&lrec);
        P2D_SetColors(colBack, colSetText);
      }
      else {
        P2D_SetColors(colText, colBack);
      }

      /*display the snprintf content, excepting the '-'*/
      if(digitId < len) {
        glyph = str[len - digitId - 1];
        if(glyph == (uint8_t)'-') glyph = (uint8_t)'0'; /*will be displayed at end*/
      }
      /*for small value (i.e. digitId >= strlen), fill with '0'*/
      else {
        glyph = (uint8_t)'0';
      }

      P2D_PutGlyph(lrec.x, lrec.y, glyph);
    }

    /*display the sign, only if negative*/
    if(bNeg) {
      P2D_SetColors(colText, colBack);
      lrec.x = GetDigitCoord(rval, digitId);
      P2D_PutGlyph(lrec.x, lrec.y, (uint8_t)'-');
    }

    /*display the dot, if any*/
    if(rval->posDot > 0) {
      P2D_SetColor(colText);
      lrec.x = GetDigitCoord(rval, rval->posDot - 1) - rval->spacing;
      P2D_SetColors(colText, colBack);
      P2D_PutGlyph(lrec.x, lrec.y, (uint8_t) '.');
    }

    /*rect*/
    P2D_SetColor(colLine);
    P2D_Rect(&(g_obj->rec));
  }
}