Ergebnis 1 bis 2 von 2
Like Tree1Likes
  • 1 Post By xorg1990

Thema: FMS Telegramme mit Javascript modulieren.

  1. #1
    Avatar von xorg1990
    xorg1990 ist offline König
    registriert
    20-12-2013
    Beiträge
    872

    FMS Telegramme mit Javascript modulieren.

    Hallo Leute, ich war ja ewig nicht mehr im Forum aktiv. Einerseits weil ich in letzter zeit nur Mikroprozessoren programmiert habe und anderseits war ich mit Sport treiben beschäftigt. Tja, Sport treiben wäre zwar noch für mich möglich, aber leder ist mir die Achillessehne davon geflogen.

    Zu meiner Aufgabe.

    Ich habe mir vor Jahren (in der bucht) so 'ne Polizei, Feuerwehr "Pager Handgeräte" gekauft.
    Diese reagierenn auf FMS_FSK Telegramme in 1200Baud.

    Wie ein Solches Telegramm moduliert und Aufgebaut ist steht in der Technischen Richtlinie:
    https://www.lfs-bw.de/Fachthemen/Dig.../TRBOS-FMS.pdf

    Interessant sind die Punkte 4 bis 4.2 und ab Punkt 8.4 zu lesen.
    4 Übertragungsverfahren
    Die zu übertragenden Informationsinhalte werden auf der Übertragungsstrecke in kohärenter
    Unterträger-FSK (Frequenzumtastung 1200/1800 Hz) mit einer Übermittlungsgeschwindigkeit
    von 1200 bit/s ± 0,01 % gemäß CCITT-Empfehlung V 6, gesendet. Die
    dabei ausgesendeten Signale sind nach CCITT-Empfehlung V 1 für log. 1 = 1200 Hz und
    für log. 0 = 1800 Hz.
    Einer jeden Aussendung vom FMS-Leitstellengerät und vom FMS-Fahrzeuggerät geht ein
    Sendervorlauf von 200 ms ± 10 % voraus. Nach dem Sendervorlauf folgt ein Telegrammvorlauf,
    bestehend aus einer „1“-Folge mit einer Länge von 12 Bit. Der Übergang
    vom Telegrammvorlauf zur Blocksynchronisation wird durch einen „Polaritätswechsel“ gekennzeichnet.
    Die sich daran anschließende Blocksynchronisation besteht aus einem 7-
    Bit-Barker-Code mit einem Füllbit. Eine Auswertung des Telegramms erfolgt nur nach vorher
    richtig erkanntem Blocksynchronisations-Signal.
    Die Aussendung des Telegramms erfolgt im BCD-Code bzw. (soweit zutreffend) im BCDCode
    mit Pseudotetraden, wobei das niederwertigste Bit (LSB) zuerst zu übertragen ist.

    4.2 Telegrammsicherung:

    Zur Telegrammsicherung wird ein Abramson-Code mit einem Codewort der Länge n = 47
    verwendet. Das Generatorpolynom ist von der Form:
    g(x) = p (x) u (x)
    = (x6 + x + 1) (x + 1)
    = x7 + x6 + x2 + 1 mod (2)


    Die Redundanz wird durch Verarbeitung des Codewortes (40 Informationsstellen und 7
    Kontrollstellen) in einem Schieberegister nachstehender Art ermittelt. Dabei sind ri (mit
    i = 0.....6) die Reste des Divisionsalgorithmus.
    Klint ja erst mal alles einleuchtend.


    Das block-Synchronisations-byte ist im Dokument nicht wirklich beschrieben, aber auf Wikipedia:
    https://de.wikipedia.org/wiki/Funkmeldesystem
    Vor dem Datentelegramm werden zur Synchronisation der Empfänger eine Serie von 12 Bits des Wertes „1“ und anschließend das Block-Synchronisations-Byte „00011010“ übertragen.

    Mein Code schaut derweile so aus:
    Code:
    <html>
    <head>
    <style type="text/css">
    </style>
    <script>(function(n){var a=Math.min,s=Math.max;var e=function(n,a,e){var s=e.length;for(var t=0;t<s;++t)n.setUint8(a+t,e.charCodeAt(t))};var t=function(t,e){this.sampleRate=t;this.numChannels=e;this.numSamples=0;this.dataViews=[]};t.prototype.encode=function(r){var t=r[0].length,u=this.numChannels,h=new DataView(new ArrayBuffer(t*u*2)),o=0;for(var e=0;e<t;++e)for(var n=0;n<u;++n){var i=r[n][e]*32767;h.setInt16(o,i<0?s(i,-32768):a(i,32767),true);o+=2}this.dataViews.push(h);this.numSamples+=t};t.prototype.finish=function(s){var n=this.numChannels*this.numSamples*2,t=new DataView(new ArrayBuffer(44));e(t,0,"RIFF");t.setUint32(4,36+n,true);e(t,8,"WAVE");e(t,12,"fmt ");t.setUint32(16,16,true);t.setUint16(20,1,true);t.setUint16(22,this.numChannels,true);t.setUint32(24,this.sampleRate,true);t.setUint32(28,this.sampleRate*4,true);t.setUint16(32,this.numChannels*2,true);t.setUint16(34,16,true);e(t,36,"data");t.setUint32(40,n,true);this.dataViews.unshift(t);var a=new Blob(this.dataViews,{type:"audio/wav"});this.cleanup();return a};t.prototype.cancel=t.prototype.cleanup=function(){delete this.dataViews};n.WavAudioEncoder=t})(self);
    </script>
    <script>
    
    window.onload = function (){
    
    function CRC(crcBits){
      let crc = [0,0,0,0,0,0,0];
      for(i=0;i<crcBits.length;++i){
        let  doinvert = (1==crcBits[i]) ^ crc[6]; 
    
    
         crc[6] = crc[5] ^ doinvert;
            crc[5] = crc[4];
            crc[4] = crc[3];
            crc[3] = crc[2];
            crc[2] = crc[1] ^ doinvert;
            crc[1] = crc[0];
            crc[0] = doinvert;
      }
    
      crcBits.push(...crc);
      return crcBits;
    }
    
    
    let data = [];
    const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    const baud = 1200;
    const sampleRate = audioCtx.sampleRate;
    const freqLow = 1200;
    const freqHigh = 1800;
    const spb = sampleRate / baud;
    
    
    const sync_Bits = [ 0,0,0,1,1,0,1,0];
    const vorlaufBits = [1,1,1,1,1,1,1,1,1,1,1,1];
    
    
    let BOS = [1,0,0,0];//BOS Kenung (Polizei)
    let land_kenn = [0,1,0,0];//Länderkennung (Baden-würtenberg)
    //ortskennung
    let ort_kenn_nib1 = [1,1,0,0];//3
    let ort_kenn_nib2 = [0,1,0,0];//4
    //kfz kennung 
    let KFZ_kenn_nib1 = [1,0,1,0];//5
    let KFZ_kenn_nib2 = [0,1,1,0];//6
    let KFZ_kenn_nib3 = [1,1,1,0];//7
    let KFZ_kenn_nib4 = [0,0,0,1];//8
    
    
    //Fernauftrag Nr.
    let Fernauftrag = [1,0,0,1];//Fernauftrag Nr. 14
    //Baustufe 
    let baustufe = 0;//Baustufe 0
    //Richtung 
    let richtung = 0;//richtung kfz->lst
    //Taktische Kurzinformation
    let takt_kutzinfo = [0,0]; 
    
    
    
    let schlussbit = 1;
    
    let bit48 = [];
    bit48.push(...BOS,...land_kenn,...ort_kenn_nib1,...ort_kenn_nib2,...KFZ_kenn_nib1,...KFZ_kenn_nib2,...KFZ_kenn_nib3,...KFZ_kenn_nib4,...Fernauftrag,baustufe,richtung,...takt_kutzinfo);
    
    
    var transmitData = CRC(bit48.slice());
    
    
    transmitData.push(schlussbit);
    
    
    
    transmitData.unshift(...sync_Bits);
    transmitData.unshift(...vorlaufBits);
    
    
    
    
    function pushData(freq, samples) {
        for (let i = 0; i < samples; i++) {
          let v = Math.cos(2 * Math.PI / sampleRate * i * freq);
          data.push(v);
        }
      }
    
    
    for(let i = 0; i<transmitData.length;i++){
    	if(transmitData[i] == 1){
    		pushData(freqLow, spb);
    	}else{
    		pushData(freqHigh, spb*2);
    	}
    }
    
    
    let audioBuffer = audioCtx.createBuffer(1, data.length, sampleRate);
    let F32buf = new Float32Array(data.length);
    F32buf.set(data);
    
    audioBuffer.copyToChannel(F32buf, 0);
    
    
    let encoder = new WavAudioEncoder(sampleRate, 1);//WavEncoder is global in document;
    	encoder.encode([F32buf]);//must bei inside array[]
    let blobWav = encoder.finish();
    
    var d = new Date();
                var sound = document.createElement('audio');
                sound.title = d.toUTCString();
                sound.controls = 'controls';
                sound.src = window.URL.createObjectURL(blobWav);
                sound.type = 'audio/wav';
    
     document.getElementsByTagName('body')[0].appendChild(sound);
    
    
    var newDiv0 = document.createElement("div")
    var newContent0 = document.createTextNode("RawData........:"+ bit48.join(""));
    newDiv0.appendChild(newContent0);
    document.body.appendChild(newDiv0);
    
    
    var newDiv1 = document.createElement("div")
    var newContent1 = document.createTextNode("TransmitData: "+ transmitData.join(""));
    newDiv1.appendChild(newContent1);
    document.body.appendChild(newDiv1);
    
    
    
    
    }
    </script>
    
    
    </head>
    
    <body>
    
    
    </body>
    </html>

    Zum demodulieren nutze ich FMS32: https://www.heirue-soft.de/software.

    Problem ist, die Telegramme die der Javascript code erzeugt werden nicht erkannt.
    Ich vermute den Fehler hier:
    Code:
    function pushData(freq, samples) {
        for (let i = 0; i < samples; i++) {
          let v = Math.cos(2 * Math.PI / sampleRate * i * freq);
          data.push(v);
        }
      }
    
    
    for(let i = 0; i<transmitData.length;i++){
    	if(transmitData[i] == 1){
    		pushData(freqLow, spb);
    	}else{
    		pushData(freqHigh, spb*2);
    	}
    }
    Ein paar Sachen sind Fragwürdig:
    - Was ist den gemeint mit "Polaritätswechsel"??
    -- Was ist den kohärente Unterträger-FSK
    --- ist meine crc (Abramson-Code) Berechnung richtig? Das Generator Polynom ist jedenfalls : "1000101".
    ----Was ist mit den Schlussbit, ist das 1 oder 0 oder wie??

  2. #2
    Avatar von xorg1990
    xorg1990 ist offline König
    registriert
    20-12-2013
    Beiträge
    872

    AW: FMS Telegramme mit Javascript modulieren.

    Hi, bevor sich welche den Kopf zerbersten. Ich habe es hinbekommen.

    Zuerst habe ich Kreisfrequenzen errechnet:
    Code:
    const markToneDelta = 2 * Math.PI * freqHigh / sampleRate;  
    const spaceToneDelta = 2 * Math.PI * freqLow / sampleRate;
    und dann die Phase immer aufradiert:

    Code:
    let audioLength = transmitData.length*spb;
    const audioBuffer = audioCtx.createBuffer(1, audioLength, sampleRate);
    let channelDataBuffer     = audioBuffer.getChannelData(0);
    
    let phase = 0;
    let position = 0;
    for(let i=0;i<transmitData.length;i++){
          let bit = transmitData[i];
          let tone = bit ? spaceToneDelta : markToneDelta;//markToneDelta : spaceToneDelta;
          for (let i = 0; i < spb; i++) {
            phase += tone;
            channelDataBuffer[position++] = Math.sin(phase);
          }
    
    }
    Die crc Prüfsumme ist auch richtig nur falsch herum : crcBits.push(...crc.reverse()); ist die Lösung.

    Für was ich das benötige:

    Ich möchte einfach nur 2 Temperaturen und die Uhrzeit übertragen, das aber 30km und da dieses verfahren seit 1972 in Deutschland angewandt wurde (bis 2015) scheint es ja Stabil zu laufen.
    mikdoe likes this.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •