//! 2.2.6.1 Write Value to Register
//!
//! @param dnRegNumber
//! @param drvValue
//!
USBDM_GDI_API
DiReturnT DiRegisterWrite ( DiUInt32T        dnRegNumber,
                            DiRegisterValueT drvValue ) {
   LOGGING;
   U32c  value(drvValue);
   USBDM_ErrorCode rc = BDM_RC_OK;

//   Logging::print("DiRegisterWrite(0x%X(%d) <= 0x%08X)\n", dnRegNumber, dnRegNumber, (uint32_t)value);

   CHECK_ERROR_STATE();

   if (dnRegNumber>cfv234regID_FIRST_DEBUG_REG) {
      dnRegNumber -= cfv234regID_FIRST_DEBUG_REG;
      Logging::print("DiRegisterWriteD(0x%X(%s) <= 0x%08X)\n", dnRegNumber, getCFVxDebugRegName(dnRegNumber), (uint32_t)value);
      rc = USBDM_WriteDReg(dnRegNumber,value);
   }
   else if (dnRegNumber > cfv234regID_FIRST_CONTROL_REG) {
      dnRegNumber -= cfv234regID_FIRST_CONTROL_REG;
      Logging::print("DiRegisterWriteC(0x%X(%s) <= 0x%08X)\n", dnRegNumber, getCFVxControlRegName(dnRegNumber), (uint32_t)value);
      rc = USBDM_WriteCReg(dnRegNumber,value);
   }
   else {
      switch (dnRegNumber) {
         case cfv234regID_pc :
            Logging::print("DiRegisterWrite(0x%X(%s) <= 0x%08X)\n", CFVx_CRegPC, getCFVxControlRegName(CFVx_CRegPC), (uint32_t)value);
            rc = USBDM_WriteCReg(CFVx_CRegPC,value);
            break;
         case cfv234regID_sr :
            Logging::print("DiRegisterWrite(0x%X(%s) <= 0x%08X)\n", CFVx_CRegSR, getCFVxControlRegName(CFVx_CRegSR), (uint32_t)value);
            rc = USBDM_WriteCReg(CFVx_CRegSR,value);
            break;
         default : // D0-7, A0-7
            if (dnRegNumber<=cfv234regID_a7) {
               Logging::print("DiRegisterWrite(0x%X(%s) <= 0x%08X)\n", dnRegNumber, getCFVxRegName(dnRegNumber), (uint32_t)value);
               rc = USBDM_WriteReg(dnRegNumber,value);
            }
            else {
               Logging::print("DiRegisterWrite(illegal reg# = 0x%X (%d)\n", dnRegNumber, dnRegNumber);
               rc = BDM_RC_ILLEGAL_PARAMS;
            }
            break;
      }
   }
   if (rc != BDM_RC_OK) {
//      Logging::error("DiRegisterWrite(0x%X,%s) Failed, reason= %s\n",
//            dnRegNumber, DSC_GetRegisterName(regNum), USBDM_GetErrorString(rc));
      return setErrorState(DI_ERR_NONFATAL, rc);
   }
   return setErrorState(DI_OK);
}
//! (CFv1) Write Control register
//!
//! @param regNo Register #
//! @param value 32-bit value
//!
OSBDM_API void _opensourcebdm_write_creg(unsigned char regNo, unsigned int value) {

   if (regNo>15) {// debugger tries to write to illegal registers !
      print("_opensourcebdm_write_creg(%d,%X) - illegal register\r\n", regNo, value);
      return;
   }
   USBDM_WriteCReg(regNo, value);
}
//!  2.2.8.6 Get DI Execution/Exit Status
//!
//! @param pdesExitStatus
//!
//! @return \n
//!     DI_OK              => OK \n
//!     DI_ERR_FATAL       => Error see \ref currentErrorString
//!
USBDM_GDI_DECLSPEC
DiReturnT DiExecGetStatus ( pDiExitStatusT pdesExitStatus ) {
   LOGGING;

   USBDM_ErrorCode      BDMrc;
   static DiExitCauseT  lastStatus     = DI_WAIT_USER;

   // Defaults
   pdesExitStatus->dscCause = DI_WAIT_UNKNOWN;
   pdesExitStatus->dwBpId   = 0; // bkpt ID?
   pdesExitStatus->szReason = (DiStringT)"unknown state";
   if (bdmOptions.autoReconnect) {
      USBDM_ErrorCode bdmRc = bdmInterface->targetConnectWithRetry(softConnectOptions);
      if (bdmRc != BDM_RC_OK) {
         log.print("=> DI_ERR_COMMUNICATION\n");
         return setErrorState(DI_ERR_COMMUNICATION, bdmRc);
      }
   }
   log.print("Calling USBDM_GetBDMStatus()\n");
   USBDMStatus_t USBDMStatus;
   USBDM_GetBDMStatus(&USBDMStatus);
//   pdesExitStatus->szReason = (DiStringT)getBDMStatusName(&USBDMStatus);
   if (USBDMStatus.connection_state == SPEED_NO_INFO) {
      log.print("=> NO_INFO\n");
      return setErrorState(DI_OK);
//      log.print("DiExecGetStatus()=>DI_ERR_COMMUNICATION\n");
//      return setErrorState(DI_ERR_NONFATAL, "Connection with target lost");
   }
   if (USBDMStatus.reset_recent == RESET_DETECTED) {
      log.print("=> Target has been reset\n");
      mtwksDisplayLine("Target RESET detected\n");
   }
   unsigned long status;
   BDMrc = USBDM_ReadStatusReg(&status);
   if (BDMrc != BDM_RC_OK) {
      log.print("=> Status read failed\n");
      return setErrorState(DI_OK);
//      return setErrorState(DI_ERR_NONFATAL, BDMrc);
   }
   if ((status&CFV1_XCSR_ENBDM) == 0) {
      log.print("=> ENBDM=0\n");
      return setErrorState(DI_OK);
//      log.print("DiExecGetStatus()=>DI_ERR_NONFATAL\n");
//      return setErrorState(DI_ERR_NONFATAL, "Connection with target lost");
   }
   if ((status&CFV1_XCSR_STOP) != 0) {
      // Stopped - low power sleep, treated as running
//      pdesExitStatus->dscCause = DI_WAIT_EXTERNAL|DI_WAIT_MISCELLANEOUS;
      pdesExitStatus->dscCause = DI_WAIT_RUNNING;
      pdesExitStatus->szReason = (DiStringT)"Target Stopped (Low power)...";
      if (lastStatus != pdesExitStatus->dscCause) {
//         log.print("DiExecGetStatus() status change => DI_WAIT_EXTERNAL|DI_WAIT_MISCELLANEOUS, (%s)\n",
         log.print("DiExecGetStatus() status change => DI_WAIT_RUNNING, (%s)\n",
               pdesExitStatus->szReason);
      }
   }
   else if ((status&CFV1_XCSR_HALT) != 0) {
      // Halted - in debug halted mode
      pdesExitStatus->dscCause = DI_WAIT_MISCELLANEOUS;
      pdesExitStatus->szReason = (DiStringT)"Debug Halted";
      if (lastStatus != pdesExitStatus->dscCause) {
         log.print("Status change => DI_WAIT_MISCELLANEOUS, (%s)\n",
               pdesExitStatus->szReason);
#if (TARGET==CFV1) && defined(CONVERT_RESETS_TO_EXCEPTIONS)
         // Read-write PC on halt
         // This causes Illegal Operand and Address Errors to be converted from
         // Resets to Exceptions.
         // Without this code the debugger is a bit misleading as it halts at the
         // start of the exception handler but then does the reset on resume!
         unsigned long PCValue;
         USBDM_ReadCReg(CFV1_CRegPC, &PCValue);
         USBDM_WriteCReg(CFV1_CRegPC, PCValue);
#endif
      }
   }
   else {
      // Processor executing
      pdesExitStatus->dscCause = DI_WAIT_RUNNING;
      pdesExitStatus->szReason = (DiStringT)"Running";
      if (lastStatus != pdesExitStatus->dscCause) {
         log.print("Status change => DI_WAIT_RUNNING, (%s)\n",
               pdesExitStatus->szReason);
      }
   }
   log.print("Reason = %s\n", pdesExitStatus->szReason);
   lastStatus = pdesExitStatus->dscCause;
   return setErrorState(DI_OK);
}
//! 2.2.6.1 Write Value to Register
//!
//! @param dnRegNumber
//! @param drvValue
//!
USBDM_GDI_DECLSPEC
DiReturnT DiRegisterWrite ( DiUInt32T        dnRegNumber,
                            DiRegisterValueT drvValue ) {
   LOGGING;
   U32c            value(drvValue);
   USBDM_ErrorCode rc  = BDM_RC_OK;

   log.print("(0x%X(%d) <= 0x%08X)\n", dnRegNumber, dnRegNumber, (uint32_t)value);

   CHECK_ERROR_STATE();

   if (dnRegNumber>cfv1regID_FIRST_DEBUG_regID_BYTE) {
      switch (dnRegNumber) {
         case cfv1regID_xcsr_byte :
            rc = USBDM_WriteControlReg(value);
            if (rc != BDM_RC_OK) {
               log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                     "XCSR.byte", dnRegNumber, USBDM_GetErrorString(rc));
               return setErrorState(DI_ERR_NONFATAL, rc);
            }
            break;
         case cfv1regID_csr2_byte :
            rc = USBDM_WriteDReg(CFV1_DRegCSR2byte,value);
            if (rc != BDM_RC_OK) {
               log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                     "CSR2.byte", dnRegNumber, USBDM_GetErrorString(rc));
               return setErrorState(DI_ERR_NONFATAL, rc);
            }
            break;
         case cfv1regID_csr3_byte :
            rc = USBDM_WriteDReg(CFV1_DRegCSR3byte,value);
            if (rc != BDM_RC_OK) {
               log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                     "CSR3.byte", dnRegNumber, USBDM_GetErrorString(rc));
               return setErrorState(DI_ERR_NONFATAL, rc);
            }
            break;
         default                  :
            log.print("DiRegisterWrite(Illegal Reg# 0x%X(%d)\n", dnRegNumber, dnRegNumber);
            rc = BDM_RC_ILLEGAL_PARAMS;
            break;
      }
   }
   else if (dnRegNumber>cfv1regID_FIRST_DEBUG_REG) {
      int regNum = dnRegNumber-cfv1regID_FIRST_DEBUG_REG;
      rc = USBDM_WriteDReg(regNum,value);
      if (rc != BDM_RC_OK) {
         log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
               getCFV1DebugRegName(regNum), dnRegNumber, USBDM_GetErrorString(rc));
         return setErrorState(DI_ERR_NONFATAL, rc);
      }
   }
   else if (dnRegNumber > cfv1regID_FIRST_CONTROL_REG) {
      int regNum = dnRegNumber-cfv1regID_FIRST_CONTROL_REG;
      rc = USBDM_WriteCReg(regNum,value);
      if (rc != BDM_RC_OK) {
         log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
               getCFV1ControlRegName(regNum), dnRegNumber, USBDM_GetErrorString(rc));
         return setErrorState(DI_ERR_NONFATAL, rc);
      }
   }
   else {
      switch (dnRegNumber) {
         case cfv1regID_pc : /*  PC */
            if (!pcWritten) {
               log.print("Saving initial PC write = 0x%08X)\n", (uint32_t)value);
               pcWritten    = true;
               pcResetValue = value;
            }
            rc = USBDM_WriteCReg(CFV1_CRegPC,value);
            if (rc != BDM_RC_OK) {
               log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                     "PC", dnRegNumber, USBDM_GetErrorString(rc));
               return setErrorState(DI_ERR_NONFATAL, rc);
            }
            break;
         case cfv1regID_sr :
            rc = USBDM_WriteCReg(CFV1_CRegSR,value);
            if (rc != BDM_RC_OK) {
               log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                     "SR", dnRegNumber, USBDM_GetErrorString(rc));
               return setErrorState(DI_ERR_NONFATAL, rc);
            }
            break;
         default : // D0-7, A0-7
            if (dnRegNumber>15) {
               log.print("DiRegisterWrite(Illegal Reg# 0x%X(%d)\n", dnRegNumber, dnRegNumber);
               rc = BDM_RC_ILLEGAL_PARAMS;
            }
            else {
               rc = USBDM_WriteReg(dnRegNumber,value);
               if (rc != BDM_RC_OK) {
                  log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                        getCFV1RegName(dnRegNumber), dnRegNumber, USBDM_GetErrorString(rc));
                  return setErrorState(DI_ERR_NONFATAL, rc);
               }
            }
            break;
      }
   }
   if (rc != BDM_RC_OK) {
      log.error("0x%X Failed, reason= %s\n",
           dnRegNumber, USBDM_GetErrorString(rc));
      return setErrorState(DI_ERR_NONFATAL, rc);
   }
   return setErrorState(DI_OK);
}
USBDM_ErrorCode BdmInterface_CFV1::writePC(unsigned long regValue) {
   return USBDM_WriteCReg(CFV1_CRegPC, regValue);
};