Ergebnis 1 bis 2 von 2
-
27-12-2020, 15:56 #1
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.
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); } }
- 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??
-
28-12-2020, 11:22 #2
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;
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); } }
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.
Lesezeichen