
{ Loran-C signal convolution filter code generator   Matthias Koch 2014 }

uses sysutils, math, zahlenzauber;

type tsignal = array[0..99990] of longint;

var puls : tsignal;
    gri : longint = 74990;


function loranpuls(i : longint) : single;
const k : single = 1/72.5e-6;
      f : single = 100000;

var t : single;
begin
  if i < 0 then loranpuls := 0
  else
  begin
    t := 0.000001 * i; // Schrittweite 1 us.
    loranpuls := k*k*t*t * exp (-2*(k*t-1)) * sin(2*pi*f*t);
  end;
end;

procedure pulszug;
var i : longint;
    summe : longint;
    abssumme : longint;
    nichtnull : integer;
    assembler, assemblerflott : text;
    filterkoeffizient : word;
begin
  assign(assembler, 'filter.s');
  rewrite(assembler);
  assign(assemblerflott, 'filter-fast.s');
  rewrite(assemblerflott);

  writeln(assembler);
  writeln(assembler, '  movs r0, #0  @ Clear result low');
  writeln(assembler, '  movs r1, #0  @ Clear result high');
  writeln(assembler);

  writeln(assemblerflott);
  writeln(assemblerflott, '  movs r0, #0  @ Clear result low');
  writeln(assemblerflott, '  movs r1, #0  @ Clear result high');
  writeln(assemblerflott);

//  for i := 0 to gri - 1 do puls[i] := round(1000 * loranpuls(i) );
  for i := 0 to gri - 1 do puls[i] := round(795 * loranpuls(i) );
  summe := 0;
  abssumme := 0;
  nichtnull := 0;
  for i := 0 to 500 do 
  begin
    writeln(i, ' ', puls[i]);

    // Assembler filter code output
    if puls[i] <> 0 then
    begin

      if puls[i] >= 0 then filterkoeffizient := puls[i]
                      else filterkoeffizient := $10000 + puls[i];

      if i <= $FF then writeln(assembler, '  adds r2, r6, #', i)
                  else writeln(assembler, '  addw r2, r6, #', i);

      writeln(assembler, '  lsls r2, #1');
      writeln(assembler, '  subs r3, r2, #0x10000');
      writeln(assembler, '  ite hs');
      writeln(assembler, '    addhs r2, r3, #0x20000000');
      writeln(assembler, '    addlo r2,     #0x10000000');
      writeln(assembler, '  ldrh r2, [r2]');
      writeln(assembler, '  movw r3, #0x', word2hex(filterkoeffizient), ' @ ', puls[i]);
      writeln(assembler, '  smlalbb r0, r1, r2, r3');
      writeln(assembler);

      writeln(assemblerflott, '  ldrh r2, [r6, #', i shl 1, '] @ Sample ', i);
      writeln(assemblerflott, '  movw r3, #0x', word2hex(filterkoeffizient), ' @ ', puls[i]);
      writeln(assemblerflott, '  smlalbb r0, r1, r2, r3');
      writeln(assemblerflott);
    end;
    // Finished filter code generation

    if puls[i] <> 0 then inc(nichtnull);
    summe := summe + puls[i];
    abssumme := abssumme + abs(puls[i]);
  end;

  writeln('Sum of coefficients: ', summe, ' Sum of absolute coeffizients: ', abssumme, ' Number of coeffizients <> 0: ', nichtnull);

  writeln(assembler, '  movs tos, r0 @ Return low part of result');
  writeln(assembler, '  bx lr');
  writeln(assembler);
  writeln(assembler, '  @ Sum of coefficients: ', summe, ' Sum of absolute coeffizients: ', abssumme, ' Number of coeffizients <> 0: ', nichtnull);
  writeln(assembler);
  close(assembler);

  writeln(assemblerflott, '  movs tos, r0 @ Return low part of result');
  writeln(assemblerflott, '  bx lr');
  writeln(assemblerflott);
  writeln(assemblerflott, '  @ Sum of coefficients: ', summe, ' Sum of absolute coeffizients: ', abssumme, ' Number of coeffizients <> 0: ', nichtnull);
  writeln(assemblerflott);
  close(assemblerflott);
end;


{

r0 Summe Low
r1 Summe High
r2 Wert aus Puffer
r3 Filterkoeffizient
r4
r5
r6=tos enthält Stelle, an der losgerechnet werden soll

}

begin
  pulszug;
end.
