/**
 *  Set watchpoint for data comparison with another 2 comparator used for data address matching
 *  Note : Will automatically set processor to CORE_DEBUG_MODE
 *
 *  Input : matchingCompNumber1 is the first comparator going to be used for data address matching
 *          Possible value :
 *              COMPARATOR_0               DWT Comparator Number 0
 *              COMPARATOR_2               DWT Comparator Number 2
 *              COMPARATOR_3               DWT Comparator Number 3
 *
 *          address1 is the first address to be used for data address matching
 *          addressMask1 is the mask going to be applied to the first address 
 *          Possible value :
 *              WATCHPOINT_MASK_NOTHING  		  Compare all 32 bits of address set in DWT_COMPn 
 *							WATCHPOINTMASK_BIT0 			    Ignore Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINTMASK_BIT1_BIT0		  Ignore Bit1 and Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINTMASK_BIT2_BIT0		  Ignore Bit2 to Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINTMASK_BIT3_BIT0		  Ignore Bit3 to Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINT_MASK_BIT4_BIT0     Ignore Bit4 to Bit 0 of address set in DWT_COMPn during comparison
 *                        ""                                              ""
 *							WATCHPOINT_MASK_BIT12_BIT0		Ignore Bit12 to Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINT_MASK_BIT13_BIT0		Ignore Bit13 to Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINT_MASK_BIT14_BIT0	  Ignore Bit14 to Bit 0 of address set in DWT_COMPn during comparison
 *
 *          matchingCompNumber2 is the second comparator going to be used for data address matching
 *          Possible value :
 *              COMPARATOR_0               DWT Comparator Number 0
 *              COMPARATOR_2               DWT Comparator Number 2
 *              COMPARATOR_3               DWT Comparator Number 3
 *
 *          address2 is the second address to be used for data address matching
 *          addressMask2 is the mask going to be applied to the second address 
 *          Possible value :
 *              WATCHPOINT_MASK_NOTHING  		  Compare all 32 bits of address set in DWT_COMPn 
 *							WATCHPOINT_MASK_BIT0  			  Ignore Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINT_MASK_BIT1_BIT0,		Ignore Bit1 and Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINT_MASK_BIT2_BIT0,		Ignore Bit2 to Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINT_MASK_BIT3_BIT0,		Ignore Bit3 to Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINT_MASK_BIT4_BIT0     Ignore Bit4 to Bit 0 of address set in DWT_COMPn during comparison
 *                        ""                                              ""
 *							WATCHPOINT_MASK_BIT12_BIT0		Ignore Bit12 to Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINT_MASK_BIT13_BIT0		Ignore Bit13 to Bit 0 of address set in DWT_COMPn during comparison
 *							WATCHPOINT_MASK_BIT14_BIT0	  Ignore Bit14 to Bit 0 of address set in DWT_COMPn during comparison
 *
 *          matchedData is the data going to be matched/compared
 *          dataSize is the data size going to be compared
 *          Possible value :
 *              WATCHPOINT_BYTE         
 *              WATCHPOINT_HALFWORD
 *              WATCHPOINT_WORD
 *
 *          accessMode is the access mode for the watchpoint
 *          Possible value :
 *              WATCHPOINT_READ         Watchpoint on read access
 *              WATCHPOINT_WRITE        Watchpoint on write access
 *              WATCHPOINT_READWRITE    Watchpoint on read/write access
 *
 *  Output :  return 0 if watchpoint is set 
 *            return -1 if invalid comparator is selected 
 */
int setDataWatchpoint_MatchingTwoComparator(int matchingCompNumber1,uint32_t address1,Watchpoint_AddressMask addressMask1,
                                            int matchingCompNumber2,uint32_t address2,Watchpoint_AddressMask addressMask2,
                                            uint32_t matchedData,Watchpoint_DataSize dataSize,Watchpoint_AccessMode accessMode)
{
  int result = 0 ;
  int valid1 = 0 , valid2 = 0 ;
  uint32_t configData = 0 ;
  
  valid1 = checkForValidDWTComparator(matchingCompNumber1);
  valid2 = checkForValidDWTComparator(matchingCompNumber2);

  if(matchingCompNumber1 == 1 || matchingCompNumber2 == 1 || valid1 == -1 || valid2 == -1)
    return -1 ;

  configData = (matchingCompNumber2 << 16) + (matchingCompNumber1 << 12) + (dataSize << 10) + (DATA_COMPARISON << 8) + accessMode ;

  setAddressWatchpoint(matchingCompNumber1,address1,addressMask1,DISABLE_DWTCOMPARATOR);
  setAddressWatchpoint(matchingCompNumber2,address2,addressMask2,DISABLE_DWTCOMPARATOR);
  
  memoryWriteWord((uint32_t)(&DWT_COMP[1].FUNCTION),DISABLE_DWTCOMPARATOR); //disable selected comparator first
  
  memoryWriteWord((uint32_t)(&DWT_COMP[1].COMP),matchedData);
  memoryWriteWord((uint32_t)(&DWT_COMP[1].MASK),WATCHPOINT_MASK_NOTHING);
  memoryWriteWord((uint32_t)(&DWT_COMP[1].FUNCTION),configData);
  
  return result ;
}
/*------------------setAddressWatchpoint--------------*/
void test_setAddressWatchpoint_given_DWT_COMP0_address_0x12345677_mask_WATCHPOINTMASK_BIT0_WATCHPOINT_READ()
{

  //Faking CSW to Byte Size
  cswDataSize = CSW_BYTE_SIZE ;

  //Enable Global enable for DWT
  emulateSwdRegisterWrite(TAR_REG,SWD_AP,4,DEMCR_REG+3);
  emulateSwdRegisterWrite(DRW_REG,SWD_AP,4,ENABLE_DWT_ITM << 24);

  // Set CSW to Word Size
	emulateSwdRegisterWrite(SELECT_REG, SWD_DP, OK, SELECT_BANK0);
	emulateSwdRegisterWrite(CSW_REG, SWD_AP, OK, (CSW_DEFAULT_MASK | CSW_WORD_SIZE));
  
  // Disable comparator first
	emulateSwdRegisterWrite(TAR_REG,SWD_AP,4,(uint32_t)(&DWT_COMP[0].FUNCTION));
	emulateSwdRegisterWrite(DRW_REG,SWD_AP,4,0);
  
  // Program comparator 
  emulateSwdRegisterWrite(TAR_REG,SWD_AP,4,(uint32_t)(&DWT_COMP[0].COMP));
	emulateSwdRegisterWrite(DRW_REG,SWD_AP,4,0x12345677);
 
  // Program mask 
  emulateSwdRegisterWrite(TAR_REG,SWD_AP,4,(uint32_t)(&DWT_COMP[0].MASK));
	emulateSwdRegisterWrite(DRW_REG,SWD_AP,4,WATCHPOINT_MASK_BIT0);
  
  // Program function
	emulateSwdRegisterWrite(TAR_REG,SWD_AP,4,(uint32_t)(&DWT_COMP[0].FUNCTION));
	emulateSwdRegisterWrite(DRW_REG,SWD_AP,4,WATCHPOINT_READ);
  
  
  TEST_ASSERT_EQUAL(0,setAddressWatchpoint(COMPARATOR_0,0x12345677,WATCHPOINT_MASK_BIT0,WATCHPOINT_READ));
}