Question

From Lenze manual

Code number (C1, C2)
Standard addressing
The meaning of the code numbers and the assigned parameters can be obtained from
the code table (see chapter 8.2). When transmitting data, the code number are
coded as follows:
The following calculation determines the two ASCII digits from the code number
(value range: 0..6229) (value range: 48dec 127dec):
C1 = INTEGER((REMAINDER(code number/790))/10) + 48dec
C2 = REMAINDER(REMAINDER(code number/790)/10) + 
     INTEGER(code number/790) x 10 + 48dec

Procedure for calculating C1 and C2 from codenumber.

procedure pCodeNumberToC1C2(CodeNumber: Word; var C1, C2: Byte);
begin
  C1 := Byte((CodeNumber mod 790) div 10) + 48;
  C2 :=     ((CodeNumber mod 790) mod 10) + 48 + 10 * Byte(CodeNumber div 790);
end;

But, how to calculate it the other way without the aweful:

function fC1C2ToCodeNumber(iC1, iC2: Byte): Word;
var
  C1, C2: Byte;
  i: Integer;
Begin
  Result := 0;
  For i := 0 to 6229 Do Begin
    pCodeNumberToC1C2(i, C1, C2);
    if (C1 = iC1) and (C2 = iC2) Then Result := i;
  End;
  Result := cn;
End;
Was it helpful?

Solution

Let's 
N = p * 790 + q
then
c1 = 48 + q div 10
c2 = 48 + q mod 10 + 10 * p
so
p = (c2-48) div 10
q = (c2-48) mod 10 + (c1-48) * 10

test:

var
  c1, c2: Byte;
  n, p, q, t: Word;
begin
  for t := 0 to 6229 do begin
    n := t;
    pCodeNumberToC1C2(n, c1, c2);
    p := (c2-48) div 10;
    q := (c2-48) mod 10 + (c1-48) * 10;
    n := 790*p+q;
    if n <> t then
      Memo1.Lines.Add('Failed at ' + IntToStr(t))
  end;

Final:

function C1C2ToCodeNumber(C1, C2: Byte): Word;
begin
Result := ((C2 - 48) div 10) * 790 + ((C2 - 48) mod 10 + (C1 - 48) * 10);
end;

OTHER TIPS

As an alternative to arithmetic you could consider a lookup table. At the cost of memory, this gives you better performance. The code looks like this:

const
  CodeNumberTable: array [48..126, 48..127] of Word = (
    .... code removed because of Sack Overflow post size limitation
  );

const
  MinC1 = low(CodeNumberTable);
  MinC2 = high(CodeNumberTable);
  MaxC1 = low(CodeNumberTable[MinC1]);
  MaxC2 = high(CodeNumberTable[MinC1]);

type
  EInvalidParameters = class(Exception);

function fC1C2ToCodeNumber(iC1, iC2: Byte): Word;
begin
  if not InRange(iC1, MinC1, MaxC1) then
    raise EInvalidParameters.CreateFmt(
      'iC1 (%d) must be in the range %d to %d',
      [iC1, MinC1, MaxC1]
    );
  if not InRange(iC2, MinC2, MaxC2) then
    raise EInvalidParameters.CreateFmt(
      'iC2 (%d) must be in the range %d to %d',
      [iC2, MinC2, MaxC2]
    );
  Result := CodeNumberTable[iC1, iC2];
  if Result=high(Word) then
    raise EInvalidParameters.CreateFmt(
      'CodeNumber not defined for iC1=%d, ic2=%d',
      [iC1, iC2]
    );
end;

I can supply the table via paste bin if you are interested.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top