maanantai, 3. joulukuu 2018

SDRSharp TETRA demodulator plug-in SDS decoding

SDR# TETRA demodulator plug-in NetInfo can show different SDS message types, e.g.

SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:OTAK
SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:DOTAM
SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Concatenated_SDS_msg DATA:'0......'

SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Concatenated_SDS_message MessageType:SDS-Report Delivery_status:xxx TextCodingScheme:Available_for_user_application_definition_xx TimeStampUsed:No DATA:'0...'
Location System solution in TErrestrial Trunked RAdio
http://lib.tkk.fi/Dipl/2010/urn100134.pdf

SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Location_System MessageType:SDS-Transfer DATA:'0....' LocationSystemCodingScheme:xxx

Carrier:xxxx TimeSlot:x SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Wireless_datagram

SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:End_to_end_encrypted_message
SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Simple_AGNSS_service

SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Location_System MessageType:SDS-Ack Delivery_status:xxx

SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Simple_immediate_text TextCodingScheme:Available_for_user_application_definition_xx

SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Wireless_Control_Message

SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Simple_text_msg TextCodingScheme:xxx
SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Message_with_User_Data_Header
SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Location_System
SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Managed_DMO_Message

SSI:xxx D_SDS_Data Party_SSI:xxx Type:UDT-4 Length:xxx Protocol:Location_information SubType:Short_location_report Lat:x Long:x Accuracy:x Velocity:x Dir:x

lauantai, 24. marraskuu 2018

Silvercrest wireless doorbell

Silvercrest STK 36 B2 version 12/2017 (433 MHz OOK)  https://postimg.cc/TpC7xhm3
sc.jpg

I recorded IQ file with SDR# (433.946 MHz 0.25 MS/s) and with GNU Radio demodulated OOK and saved demodulated signal to wave file. https://postimg.cc/JGn3bxDR

gr.jpg

Investigating the wave file with Audacity

Transmitter sends this sequence 50 times  https://postimg.cc/Yjx8Njdz

audacity.jpg

L,L,L,L,L,S,L,L,L,S,S,L,S,S,L,L,S,L,S,S,L,S,S,S,S
Length of shortest high peak is approx 31 samples, 1 / (sample_rate / 31) ~= 1612 bps.

tbc ....

torstai, 1. marraskuu 2018

SDRSharp - screen scraping spectrum analyzer

Microsoft Spy++ download: https://social.msdn.microsoft.com/Forums/vstudio/en-US/8d06750a-8d6c-4aca-9896-6ca49a631c07/where-can-i-get-microsoft-spy?forum=vcgeneral

sdrs1.jpg
https://ibb.co/ftUusf

sdsr2.jpg

Highlight flashes window borders - find which window handle is FFT spectrum analyzer

 

notsrccopy

sdsr3.jpg
https://ibb.co/nmBw50

C# code

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr hWnd);
        [DllImport("user32.dll")]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);

        [DllImport("gdi32.dll")]
        public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest,
        int nWidth, int nHeight, IntPtr hObjectSource, int nXSrc, int nYSrc, int dwRop);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);
        [DllImport("gdi32.dll")]
        public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);

        public Form1()
        {
            InitializeComponent();
        }

        private void button_GetGFX_Click(object sender, EventArgs e)
        {
            int i = Convert.ToInt32(textBox_Handle.Text, 16);
            IntPtr hwnd = new IntPtr(i);
            IntPtr hdcSrc = GetWindowDC(hwnd);
            RECT windowRect = new RECT();
            GetWindowRect(hwnd, ref windowRect);
            int w = windowRect.right - windowRect.left;
            int h = windowRect.bottom - windowRect.top;
            IntPtr hdcDest = CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap = CreateCompatibleBitmap(hdcSrc, w, h);
            IntPtr hOld = SelectObject(hdcDest, hBitmap);
            BitBlt(hdcDest, 0, 0, w, h, hdcSrc, 0, 0, 0x00330008); // notsrccopy
            SelectObject(hdcDest, hOld);
            DeleteDC(hdcDest);
            ReleaseDC(hwnd, hdcSrc);
            pictureBox_Img.Image = Image.FromHbitmap(hBitmap);
            DeleteObject(hBitmap);
            var encoder = ImageCodecInfo.GetImageEncoders().First(c => c.FormatID == ImageFormat.Jpeg.Guid);
            var encParams = new EncoderParameters(1);
            encParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 60L);
            pictureBox_Img.Image.Save(@"c:\temp\sa.jpg", encoder, encParams);
        }
    }
}

torstai, 25. lokakuu 2018

SDRSharp TETRA plug-in: Congestion_in_infrastructure

SDR# TETRA demodulator plug-in netinfo shows congestion related param values (BS downlink) when there is congestion in infrastructure.
https://forums.radioreference.com/voice-control-channel-decoding-software/370639-sdr-tetra-demodulator-trunk-tracking-demonstration-6.html

imm_wt_vu.jpg

Disconnect_cause:Congestion_in_infrastructure D_Release

"ETSI TR 102 300-2 V1.2.1 (2013-09)
NOTE 1: Scenario 1 represents a public network; a suitable strategy for the call management in case of lack of
resources is to block the call. No pre-emption mechanisms have been considered in these simulations. The
adopted strategy consists of immediately releasing (see annex C, D, E for the call release procedure) the
call request when no resources are available.
NOTE 2: Simulated MSs are not able to support parallel transactions. When a new call is generated by the user and
the MS is busy, in case of data services (circuit and packet calls) the MS puts this parallel transaction in a
local queue; in case of voice calls it is released. When the present transaction is finished the local queue is
checked in order to give service to the queued transactions.
NOTE 3: During the call set-up procedure, the TCH assignment policy in the SwMI is an implementation option; in
the standard document two possibilities are given: early assignment and late assignment. In scenario 1
simulations late assignment has been adopted.
All network and access control parameters in the reference situation for the simulations are summarized in table 8. The
results have been evaluated for a suitable set of network scenarios that have been derived by this reference, changing
one parameter each time.
The definition of the evaluated performance given in clause 5.4 applies. In the following clauses they are presented for
each network configuration. The number of allocated traffic channels has been evaluated in order to have a low
blocking probability (< 5 %) for all the services. Before showing the overall performance, a table reports the number of
allocated channels with the associated blocking probability of different kind of services:
- full duplex calls in the same cell site, requiring 2 TCHs per call;
- half duplex calls or full duplex calls in different cell sites, requiring 1 TCH per call.
Table 8: Summary of network parameters of the reference scenario 1
Parameter Reference value
Random access: value of the timer
regulating the first access attempt (IMM)
15
Random access: maximum number of
access attempts (Nu)
5
Random access: Back off time (WT) 5 TDMA frames
Random access: Access frame length 10 access opportunities

"

Some interesting observations:
Disconnect_cause:Called_party_requires_encryption D_Release Notification_Indicator:Call_rejected_due_to_SS_AS
Disconnect_cause:Called_party_does_not_support_encryption D_Release
Disconnect_cause:SwMI_requested_disconnection D_Release Notification_Indicator:Reserved28
Disconnect_cause:Unknown_TETRA_identity D_Release Notification_Indicator:Reserved55
Disconnect_cause:Congestion_in_infrastructure D_Release Notification_Indicator:Identity_presentation_restricted
Disconnect_cause:Unknown_external_subscriber_identity D_Release
Disconnect_cause:Called_party_is_under_the_same_DM_GATE_of_the_calling_party D_Release

D-STATUS SSI:xxxxxxx IDX:000 IDT:1 ENCR:0
Type:UDT-4 Length:697 Protocol:DOTAM

 

sunnuntai, 21. lokakuu 2018

Arduino/SX1278: Mobitex-1200 462.325 MHz ?

Dragino Lora Module (Semtech SX1278) for Arduino can demodulate FSK, GFSK, MSK and GMSK.
SX1278 datasheet: https://cdn-shop.adafruit.com/product-files/3179/sx1276_77_78_79.pdfhttps://cdn-shop.adafruit.com/product-files/3179/sx1276_77_78_79.pdf
Dragino Lora Module: http://wiki.dragino.com/index.php?title=Lora_Shield

msk-packet-edit.jpg
#define SYNC_VALUE          0xCC

    // Bits 7-6: AutoRestartRxMode, 01  On, without waiting for the PLL to re-lock
    // Bit 4: Enables the Sync word generation and detection: 0 =>  Off, 1 =>  On
    // Bit 5: Sets the polarity of the Preamble. 0  0xAA, 1  0x55
    // Bits 2-0: Size of the Sync word (SyncSize + 1)
    b = readSPI(RegSyncConfig);
    bitClear(b, 7);
    bitSet(b, 6);
    bitSet(b, 4);
    bitClear(b, 5);
    bitClear(b, 2);
    bitClear(b, 1);
    bitSet(b, 0);
    writeSPI(RegSyncConfig, b);
    writeSPI(RegSyncValue1, SYNC_VALUE);
    writeSPI(RegSyncValue2, SYNC_VALUE);
    writeSPI(RegSyncValue3, SYNC_VALUE);

------------------------------------------------------------------------------------------------------------------------------------------------

#include <SPI.h>

#define SERIAL_SPEED        19200
#define BPS                 1200
#define FREQ                462.325303
#define STATE_SLEEP         0
#define STATE_STANDBY       1
#define STATE_FSRX          4
#define STATE_RX            5
#define S_DELAY             10
#define L_DELAY             100
#define RX_BUFFER_LEN       255
#define SX_BITRATE          "BPS "
#define SX_FREQ             "Frequency "
#define SX_IRQ1_TXT         "RegIrqFlags1_value "
#define SX_IRQ2_TXT         "RegIrqFlags2_value "
#define SX_VERSION          "Version code of the chip "
#define RSSI_THRESHOLD      180             // -rssi/2
#define CH_FILTER_BW        B00000101       // 25 kHz 00100 31.3 kHz 10100 20.8 kHz 00101 15.6 kHz
#define SYNC_VALUE          0xCC
#define PRINT_IRQ_CHG       1

#define RegFifo             0x00
#define RegOpMode           0x01
#define RegBitrateMsb       0x02
#define RegBitrateLsb       0x03
#define RegFrfMsb           0x06
#define RegFrfMid           0x07
#define RegFrfLsb           0x08
#define RegPaRamp           0x0a
#define RegRssiConfig       0x0e
#define RegRssiThresh       0x10
#define RegRxBw             0x12
#define RegOokPeak          0x14
#define RegPreambleDetect   0x1f
#define RegSyncConfig       0x27
#define RegSyncValue1       0x28
#define RegSyncValue2       0x29
#define RegSyncValue3       0x2a
#define RegPacketConfig1    0x30
#define RegPacketConfig2    0x31
#define RegPayloadLength    0x32
#define RegIrqFlags1        0x3e
#define RegIrqFlags2        0x3f
#define RegVersion          0x42

#define SX_OSC_FREQ         32000000
#define SX_RESET            9
#define SX_RESET_DELAY_H    5
#define SX_RESET_DELAY_L    100
#define SPI_SS              10
#define SPI_RW_DELAY        50

uint8_t RegIrqFlags1_value;
uint8_t RegIrqFlags2_value;
uint8_t rxBuffer[RX_BUFFER_LEN];

void setup() {
  Serial.begin(SERIAL_SPEED);
  if (initSX()) {
    Serial.print(F(SX_VERSION));
    Serial.print(readSPI(RegVersion));
    Serial.println();
    delay(S_DELAY);
    startFSK();
    uint8_t b = readSPI(RegOpMode);
    bitClear(b, 6);
    bitClear(b, 5);
    writeSPI(RegOpMode, b);

    // Channel filter bandwidth control
    writeSPI(RegRxBw, CH_FILTER_BW);

    setFreq(FREQ);
    Serial.print(F(SX_FREQ));
    Serial.println(FREQ, DEC);
    setBps(BPS);
    Serial.print(F(SX_BITRATE));
    Serial.println(BPS);

    // Bits 7-6: AutoRestartRxMode, 01  On, without waiting for the PLL to re-lock
    // Bit 4: Enables the Sync word generation and detection: 0 =>  Off, 1 =>  On
    // Bit 5: Sets the polarity of the Preamble. 0  0xAA, 1  0x55
    // Bits 2-0: Size of the Sync word (SyncSize + 1)
    b = readSPI(RegSyncConfig);
    bitClear(b, 7);
    bitSet(b, 6);
    bitSet(b, 4);
    bitClear(b, 5);
    bitClear(b, 2);
    bitClear(b, 1);
    bitSet(b, 0);
    writeSPI(RegSyncConfig, b);
    writeSPI(RegSyncValue1, SYNC_VALUE);
    writeSPI(RegSyncValue2, SYNC_VALUE);
    writeSPI(RegSyncValue3, SYNC_VALUE);

    // Bits 6-5: Defines DC-free encoding/decoding performed: 00->none, 01->manchester, 10->whitening
    // Bit 7: packet format, 0 = fixed length, 1 = variable length
    // Bit 4: crc calc/check, 0 = off, 1 = on
    // Bits 2-1: Defines address based filtering in Rx: 00  None (Off)
    // Bit 3: Defines the behavior of the packet handler when CRC check fails:
    // 0 => Clear FIFO and restart new packet reception. No PayloadReady interrupt issued.
    // 1 =>  Do not clear FIFO. PayloadReady interrupt issued.
    // Bit 0: Selects the CRC and whitening algorithms:
    // 0  CCITT CRC implementation with standard whitening
    // 1  IBM CRC implementation with alternate whitening
    b = 0;
    bitSet(b, 7);
    writeSPI(RegPacketConfig1, b);

    // Bits 6-5: FSK data shaping:
    // 00 -> no shaping, 01 -> Gaussian filter BT = 1.0
    // 10 -> Gaussian filter BT = 0.5, 11 -> Gaussian filter BT = 0.3
    // Bits 3-0: Rise/Fall time of ramp up/down in FSK:
    // 1001  40 us
    b = readSPI(RegPaRamp);
    bitClear(b, 6);
    bitClear(b, 5);
    bitSet(b, 3);
    bitClear(b, 2);
    bitClear(b, 1);
    bitSet(b, 0);
    writeSPI(RegPaRamp, b);

    writeSPI(RegPayloadLength, RX_BUFFER_LEN);

    // Data processing mode: 0 => Continuous mode, 1 => Packet mode
    b = readSPI(RegPacketConfig2);
    bitSet(b, 6);
    writeSPI(RegPacketConfig2, b);

    // RSSI smoothing.
    // Defines the number of samples taken to average the RSSI result. 010 -> 8 samples
    b = readSPI(RegRssiConfig);
    bitClear(b, 2);
    bitSet(b, 1);
    bitClear(b, 0);
    writeSPI(RegRssiConfig, b);

    writeSPI(RegRssiThresh, RSSI_THRESHOLD);

    // Bit 5: enables the Bit Synchronizer:
    // 0 -> bit sync disabled (not possible in packet mode), 1 -> bit sync enabled
    b = readSPI(RegOokPeak);
    bitSet(b, 5);
    writeSPI(RegOokPeak, b);

    // RegPreambleDetect (0x1f). Enables Preamble detector when set to 1.
    // The AGC settings supersede this bit during the startup / AGC phase.
    // Bit 7: 0 -> turned off, 1 -> turned on
    // Bits 6-5: Number of Preamble bytes to detect to trigger an interrupt.
    // 00  1 byte, 10  3 bytes, 01  2 bytes
    b = readSPI(RegPreambleDetect);
    bitClear(b, 7);
    bitClear(b, 6);
    bitClear(b, 5);
    writeSPI(RegPreambleDetect, b);

    clearFifoAndFlags();

    setState(STATE_FSRX);
    delay(L_DELAY);
    setState(STATE_RX);
    delay(S_DELAY);
#if (PRINT_IRQ_CHG == 1)
    RegIrqFlags1_value = readSPI(RegIrqFlags1);
    RegIrqFlags2_value = readSPI(RegIrqFlags2);
    Serial.print(F(SX_IRQ1_TXT));
    Serial.println(RegIrqFlags1_value, BIN);
    Serial.print(F(SX_IRQ2_TXT));
    Serial.println(RegIrqFlags2_value, BIN);
#endif
  }
}

void loop() {
  uint8_t r2;
  r2 = readSPI(RegIrqFlags2);
#if (PRINT_IRQ_CHG == 1)
  uint8_t r1 = readSPI(RegIrqFlags1);
  if (r1 != RegIrqFlags1_value) {
    RegIrqFlags1_value = r1;
    Serial.print(F(SX_IRQ1_TXT));
    Serial.println(RegIrqFlags1_value, BIN);
  }
  if (r2 != RegIrqFlags2_value) {
    RegIrqFlags2_value = r2;
    Serial.print(F(SX_IRQ2_TXT));
    Serial.println(RegIrqFlags2_value, BIN);
  }
#endif
  if (bitRead(r2, 2) == 1) {
    uint8_t b = readSPI(RegPayloadLength);
    if (b > 0) {
      b = fetchData(rxBuffer, b);
      if (b > 0) {
        uint8_t n;
        for (n = 0; n < b; n++) {
          Serial.print(rxBuffer[n], HEX);
          Serial.print(";");
        }
        Serial.print(b);
        Serial.println();
      }
    }
  }
}

void clearFifoAndFlags() {
  // Flag(s) and FIFO are cleared when this bit is set
  uint8_t b = readSPI(RegIrqFlags2);
  bitSet(b, 4);
  writeSPI(RegIrqFlags2, b);
  delay(S_DELAY);
}

void setBps(uint16_t bps) {
  uint16_t baudRate = SX_OSC_FREQ / bps;
  writeSPI(RegBitrateMsb, baudRate >> 8);
  writeSPI(RegBitrateLsb, baudRate & 0xff);
}

void setFreq(float f)
{
  uint32_t lf = (f * 1000000) / 61.035;
  writeSPI(RegFrfMsb, (lf >> 16) & 0xff);
  writeSPI(RegFrfMid, (lf >> 8) & 0xff);
  writeSPI(RegFrfLsb, lf & 0xff);
}

void setState(uint8_t s) {
  uint8_t b = readSPI(RegOpMode);
  b = b | s;
  writeSPI(RegOpMode, b);
}

void startFSK()
{
  setState(STATE_SLEEP);
  delay(S_DELAY);
  uint8_t b = readSPI(RegOpMode);
  bitClear(b, 7);
  writeSPI(RegOpMode, b);
}

uint8_t fetchData(uint8_t data[], uint8_t len)
{
  for (uint8_t n = 0; n < len; n++) {
    data[n] = readSPI(RegFifo);
    if (bitRead(readSPI(RegIrqFlags2), 6) == 1) {
      return n;
    }
  }
  return 0;
}

bool initSX() {
  pinMode(SX_RESET, OUTPUT);
  resetSX();
  initSPI();
  if (readSPI(RegVersion) == 0) {
    return false;
  }
  setState(STATE_STANDBY);
  return true;
}

void resetSX() {
  digitalWrite(SX_RESET, LOW);
  delayMicroseconds(SX_RESET_DELAY_L);
  digitalWrite(SX_RESET, HIGH);
  delay(SX_RESET_DELAY_H);
}

uint8_t readSPI(uint8_t addr) {
  digitalWrite(SPI_SS, LOW);
  SPI.transfer(addr);
  delayMicroseconds(SPI_RW_DELAY);
  uint8_t v = SPI.transfer(0x00);
  digitalWrite(SPI_SS, HIGH);
  return v;
}

void writeSPI(uint8_t addr, uint8_t v) {
  digitalWrite(SPI_SS, LOW);
  SPI.transfer(addr | 0x80);
  delayMicroseconds(SPI_RW_DELAY);
  SPI.transfer(v);
  digitalWrite(SPI_SS, HIGH);
}

void initSPI()
{
  digitalWrite(SPI_SS, HIGH);
  pinMode(SPI_SS, OUTPUT);  
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);
}