-2

I was able to modify the solution provided by Brad Christie to get the results I am expecting for the Hours, Minutes, Seconds, Months, Days, and Years all of which are in BCD Format:

static Int32 GetYearFromBCD(Int32 time) 
{ 
int length = time.ToString().Length -1;
List<Int32> YearList = new List<Int32>(); 
for (Int32 i = length; i >= 0; i --) 
{ 
Int32 place = i * 4; 
Int32 val = 0x01 << place; 

Int32 curVal = (Int32)(time / val); 
if (curVal > 9 && YearList.Count > 0) 
{ 
Int32 delta = (Int32)(curVal / 10); 
YearList[YearList.Count - 1] += delta; 
curVal -= delta * 10; 
} 
YearList.Add(curVal); 
time -= curVal << place; 
} 
Int32 Year = 0; 
for (Int32 y = 0; y < YearList.Count; y++) 
Year += YearList[y] * (Int32)Math.Pow(10,(length+1 - y)-1); 
return Year; 
} 

I wanted to provide an update to this question. After the device was running for several days through New Years, I was able to full confirm that the code solution Brad posted does exactly what we will need.

I was able to confirm my suspicions that the expected value was indeed a Binary Coded Decmial, I was able to confirm that the value expected only works has a HEX value. A co-worker was able to independently confirm the time and date, using table for the standard, so I feel comfortable putting this to bed.

I was able to confirm that for whatever reason the decmial value of the data does not work, I can only conclude the data is being sent as a hex value by the device, my only concern is will other applications work in a similar method.

I appreciate everyone's help in figuring this out, some of the comments lead me down a path that allow me to figure out.

Security Hound
  • 2,577
  • 3
  • 25
  • 42

3 Answers3

3

Well, even though the numbers don't seem to make sense, this is what I came up with (giving the results you're expecting (from the examples provided). Take this through the wringer and see if it comes out with all the results you are expecting:

static Int32 GetYearFromBCD(Int32 time)
{
    List<Int32> YearList = new List<Int32>();
    for (Int32 i = 3; i >= 0; i --)
    {
        Int32 place = i * 4;
        Int32 val = 0x01 << place;

        Int32 curVal = (Int32)(time / val);
        if (curVal > 9 && YearList.Count > 0)
        {
            Int32 delta = (Int32)(curVal / 10);
            YearList[YearList.Count - 1] += delta;
            curVal -= delta * 10;
        }
        YearList.Add(curVal);
        time -= curVal << place;
    }
    Int32 Year = 0;
    for (Int32 y = 0; y < 4; y++)
        Year += YearList[y] * (Int32)Math.Pow(10,(4 - y)-1);
    return Year;
}

I'm really just taking a shot in the dark at this as the numbers you gave aren't what I would call typical. Having said that, you have to make what you're receiving work, so :shrug:.

Brad Christie
  • 100,477
  • 16
  • 156
  • 200
1

If you want to convert number to hex representation just use ToString with "x" as param:

2010.ToString("x")  output: "7da"

However, I don't really understand what to you want to achieve if you say that for 2010, you expect 200A.

empi
  • 15,755
  • 8
  • 62
  • 78
  • It's also not `0x200A` in BCD, it's `0x2010`. – Jonathan Grynspan Dec 30 '10 at 16:17
  • Then your documentation is lying. As we've all been saying, BCD for 2010 is `0x2010`. Either your documentation is mistaken as to the format of the dates, or there is a bug in the implementation that produces non-BCD values. – Jonathan Grynspan Dec 30 '10 at 17:16
  • The mistake is pretty obvious. They take `0x2000` as a base and add the century year to it. That works for `0x2000` through `0x2009` but fails on `0x2010`, giving you `0x200A` instead. – Jonathan Grynspan Dec 30 '10 at 18:12
  • Hey, you're the one defending incorrect documentation. I'm just offering a possible explanation for the discrepancy. ;) – Jonathan Grynspan Dec 30 '10 at 19:18
  • I again refer you to my previous assertion: "your documentation, stating that the data is in BCD format, is incorrect." – Jonathan Grynspan Dec 30 '10 at 19:29
0

Are you really sure that your example is correct? Why do you have a hex-number, where the first part is with base 10 and the second part is base 16?

Normal would one of these:

  • 2010 => 0x07DA
    • complete hex
  • 2010 => 0x140A
    • the number is broken half-way and each part is hex
  • 2010 => 0x2010
    • bcd encoded as found on wikipedia (where else) ;-)

After some googling and thinking here is my first idea:

  • Put everything into an BinaryReader.
  • Get all values individually out of it by calling BinaryReader.ReadByte() and cast it to an int
  • Multiply each value first by 10, then divide by 16
  • Put all of this individual values into a List<int>
  • use Math.Pow(value, 10 * (List.Count - indexOfValue)) to aggregate all these values
Oliver
  • 43,366
  • 8
  • 94
  • 151